add some Tower module integration tests (and fix a bug or two) (#37421)

* add additional test coverage for tower modules

* add test coverage for the tower_credential module

* add test coverage for the tower_user module

* fix a bug in py3 for tower_credential when ssh_key_data is specified

* add test coverage for tower_host, tower_label, and tower_project

* add test coverage for tower_inventory and tower_job_template

* add more test coverage for tower modules

- tower_job_launch
- tower_job_list
- tower_job_wait
- tower_job_cancel

* add a check mode/version assertion for tower module integration tests

* add test coverage for the tower_role module

* add test coverage for the tower_group module

* add more integration test edge cases for various tower modules

* give the job_wait module more time before failing

* randomize passwords in the tower_user and tower_group tests
This commit is contained in:
Ryan Petrello 2018-03-16 13:28:19 -04:00 committed by Sam Doran
parent 594840c1d6
commit 872a7b4a7a
32 changed files with 953 additions and 8 deletions

View file

@ -73,6 +73,14 @@ options:
client: client:
description: description:
- Client or application ID for azure_rm type. - Client or application ID for azure_rm type.
required: False
default: null
security_token:
description:
- STS token for aws type.
required: False
default: null
version_added: "2.6"
secret: secret:
description: description:
- Secret token for azure_rm type. - Secret token for azure_rm type.
@ -119,6 +127,7 @@ EXAMPLES = '''
import os import os
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_tower import tower_argument_spec, tower_auth_config, tower_check_mode, HAS_TOWER_CLI from ansible.module_utils.ansible_tower import tower_argument_spec, tower_auth_config, tower_check_mode, HAS_TOWER_CLI
try: try:
@ -184,6 +193,7 @@ def main():
authorize=dict(type='bool', default=False), authorize=dict(type='bool', default=False),
authorize_password=dict(no_log=True), authorize_password=dict(no_log=True),
client=dict(), client=dict(),
security_token=dict(),
secret=dict(), secret=dict(),
tenant=dict(), tenant=dict(),
subscription=dict(), subscription=dict(),
@ -254,13 +264,14 @@ def main():
if os.path.isdir(filename): if os.path.isdir(filename):
module.fail_json(msg='attempted to read contents of directory: %s' % filename) module.fail_json(msg='attempted to read contents of directory: %s' % filename)
with open(filename, 'rb') as f: with open(filename, 'rb') as f:
module.params['ssh_key_data'] = f.read() module.params['ssh_key_data'] = to_text(f.read())
for key in ('authorize', 'authorize_password', 'client', 'secret', for key in ('authorize', 'authorize_password', 'client',
'tenant', 'subscription', 'domain', 'become_method', 'security_token', 'secret', 'tenant', 'subscription',
'become_username', 'become_password', 'vault_password', 'domain', 'become_method', 'become_username',
'project', 'host', 'username', 'password', 'become_password', 'vault_password', 'project', 'host',
'ssh_key_data', 'ssh_key_unlock'): 'username', 'password', 'ssh_key_data',
'ssh_key_unlock'):
if 'kind' in params: if 'kind' in params:
params[key] = module.params.get(key) params[key] = module.params.get(key)
elif module.params.get(key): elif module.params.get(key):

View file

@ -140,7 +140,8 @@ def main():
if variables: if variables:
if variables.startswith('@'): if variables.startswith('@'):
filename = os.path.expanduser(variables[1:]) filename = os.path.expanduser(variables[1:])
variables = module.contents_from_file(filename) with open(filename, 'r') as f:
variables = f.read()
json_output = {'group': name, 'state': state} json_output = {'group': name, 'state': state}

View file

@ -100,7 +100,8 @@ def main():
if variables: if variables:
if variables.startswith('@'): if variables.startswith('@'):
filename = os.path.expanduser(variables[1:]) filename = os.path.expanduser(variables[1:])
variables = module.contents_from_file(filename) with open(filename, 'r') as f:
variables = f.read()
json_output = {'host': name, 'state': state} json_output = {'host': name, 'state': state}

View file

@ -87,6 +87,10 @@ def update_resources(module, p):
by name using their unique field (identity) by name using their unique field (identity)
''' '''
params = p.copy() params = p.copy()
for key in p:
if key.startswith('tower_'):
params.pop(key)
params.pop('state', None)
identity_map = { identity_map = {
'user': 'username', 'user': 'username',
'team': 'name', 'team': 'name',

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,510 @@
- name: create a tempdir for an SSH key
local_action: shell mktemp -d
register: tempdir
- name: Generate a local SSH key
local_action: "shell ssh-keygen -b 2048 -t rsa -f {{ tempdir.stdout }}/id_rsa -q -N 'passphrase'"
- name: Create a User-specific credential
tower_credential:
name: SSH Credential
organization: Default
user: admin
state: present
kind: ssh
register: result
- assert:
that:
- "result is changed"
- name: Delete a User-specific credential
tower_credential:
name: SSH Credential
organization: Default
user: admin
state: absent
kind: ssh
register: result
- assert:
that:
- "result is changed"
- name: Create a valid SSH credential
tower_credential:
name: SSH Credential
organization: Default
state: present
kind: ssh
description: An example SSH credential
username: joe
password: secret
become_method: sudo
become_username: superuser
become_password: supersecret
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
ssh_key_unlock: "passphrase"
register: result
- assert:
that:
- "result is changed"
- name: Create an invalid SSH credential (passphrase required)
tower_credential:
name: SSH Credential
organization: Default
state: present
kind: ssh
username: joe
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
ignore_errors: yes
register: result
- assert:
that:
- "result is failed"
- "'must be set when SSH key is encrypted' in result.module_stderr"
- name: Create an invalid SSH credential (ssh_key_data file is missing)
tower_credential:
name: SSH Credential
organization: Default
state: present
kind: ssh
username: joe
ssh_key_data: "{{ tempdir.stdout }}/not_a_valid_file"
ignore_errors: yes
register: result
- assert:
that:
- "result is failed"
- "'file not found' in result.msg"
- name: Create an invalid SSH credential (ssh_key_data is a directory)
tower_credential:
name: SSH Credential
organization: Default
state: present
kind: ssh
username: joe
ssh_key_data: "{{ tempdir.stdout }}"
ignore_errors: yes
register: result
- assert:
that:
- "result is failed"
- "'attempted to read contents of directory' in result.msg"
- name: Create an invalid SSH credential (Organization not found)
tower_credential:
name: SSH Credential
organization: Missing Organization
state: present
kind: ssh
username: joe
ignore_errors: yes
register: result
- assert:
that:
- "result is failed"
- "'The requested object could not be found' in result.module_stderr"
- name: Delete an SSH credential
tower_credential:
name: SSH Credential
organization: Default
state: absent
kind: ssh
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Vault credential
tower_credential:
name: Vault Credential
organization: Default
state: present
kind: vault
description: An example Vault credential
vault_password: secret-vault
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Vault credential w/ kind=ssh (deprecated)
tower_credential:
name: Vault Credential
organization: Default
state: present
kind: ssh
description: An example Vault credential
vault_password: secret-vault
register: result
- assert:
that:
- "result is changed"
- name: Delete a Vault credential
tower_credential:
name: Vault Credential
organization: Default
state: absent
kind: vault
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Network credential
tower_credential:
name: Network Credential
organization: Default
state: present
kind: net
username: joe
password: secret
authorize: true
authorize_password: authorize-me
register: result
- assert:
that:
- "result is changed"
- name: Delete a Network credential
tower_credential:
name: Network Credential
organization: Default
state: absent
kind: net
register: result
- assert:
that:
- "result is changed"
- name: Create a valid SCM credential
tower_credential:
name: SCM Credential
organization: Default
state: present
kind: scm
username: joe
password: secret
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
ssh_key_unlock: "passphrase"
register: result
- assert:
that:
- "result is changed"
- name: Delete an SCM credential
tower_credential:
name: SCM Credential
organization: Default
state: absent
kind: scm
register: result
- assert:
that:
- "result is changed"
- name: Create a valid AWS credential
tower_credential:
name: AWS Credential
organization: Default
state: present
kind: aws
username: joe
password: secret
security_token: aws-token
register: result
- assert:
that:
- "result is changed"
- name: Delete an AWS credential
tower_credential:
name: AWS Credential
organization: Default
state: absent
kind: aws
register: result
- assert:
that:
- "result is changed"
- name: Create a valid VMWare credential
tower_credential:
name: VMWare Credential
organization: Default
state: present
kind: vmware
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete an VMWare credential
tower_credential:
name: VMWare Credential
organization: Default
state: absent
kind: vmware
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Satellite6 credential
tower_credential:
name: Satellite6 Credential
organization: Default
state: present
kind: satellite6
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete a Satellite6 credential
tower_credential:
name: Satellite6 Credential
organization: Default
state: absent
kind: satellite6
register: result
- assert:
that:
- "result is changed"
- name: Create a valid CloudForms credential
tower_credential:
name: CloudForms Credential
organization: Default
state: present
kind: cloudforms
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete a CloudForms credential
tower_credential:
name: CloudForms Credential
organization: Default
state: absent
kind: cloudforms
register: result
- assert:
that:
- "result is changed"
- name: Create a valid GCE credential
tower_credential:
name: GCE Credential
organization: Default
state: present
kind: gce
username: joe
project: ABC123
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
register: result
- assert:
that:
- "result is changed"
- name: Delete a GCE credential
tower_credential:
name: GCE Credential
organization: Default
state: absent
kind: gce
register: result
- assert:
that:
- "result is changed"
- name: Create a valid AzureRM credential
tower_credential:
name: AzureRM Credential
organization: Default
state: present
kind: azure_rm
username: joe
password: secret
subscription: some-subscription
register: result
- assert:
that:
- "result is changed"
- name: Create a valid AzureRM credential with a tenant
tower_credential:
name: AzureRM Credential
organization: Default
state: present
kind: azure_rm
client: some-client
secret: some-secret
tenant: some-tenant
subscription: some-subscription
register: result
- assert:
that:
- "result is changed"
- name: Delete an AzureRM credential
tower_credential:
name: AzureRM Credential
organization: Default
state: absent
kind: azure_rm
register: result
- assert:
that:
- "result is changed"
- name: Create a valid OpenStack credential
tower_credential:
name: OpenStack Credential
organization: Default
state: present
kind: openstack
host: https://keystone.example.org
username: joe
password: secret
project: tenant123
domain: some-domain
register: result
- assert:
that:
- "result is changed"
- name: Delete a OpenStack credential
tower_credential:
name: OpenStack Credential
organization: Default
state: absent
kind: openstack
register: result
- assert:
that:
- "result is changed"
- name: Create a valid RHV credential
tower_credential:
name: RHV Credential
organization: Default
state: present
kind: rhv
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete an RHV credential
tower_credential:
name: RHV Credential
organization: Default
state: absent
kind: rhv
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Insights credential
tower_credential:
name: Insights Credential
organization: Default
state: present
kind: insights
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete an Insights credential
tower_credential:
name: Insights Credential
organization: Default
state: absent
kind: insights
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Tower-to-Tower credential
tower_credential:
name: Tower Credential
organization: Default
state: present
kind: tower
host: https://tower.example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete a Tower-to-Tower credential
tower_credential:
name: Tower Credential
organization: Default
state: absent
kind: tower
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,34 @@
- name: create a tempdir for hostvars
local_action: shell mktemp -d
register: tempdir
- name: write a file w/ hostvars
local_action:
module: lineinfile
dest: "{{ tempdir.stdout }}/vars"
line: '{"foo": "bar"}'
create: true
- name: Create a Group
tower_group:
name: Some Group
inventory: Demo Inventory
state: present
source: ec2
variables: "@{{ tempdir.stdout }}/vars"
register: result
- assert:
that:
- "result is changed"
- name: Delete a Group
tower_group:
name: Some Group
inventory: Demo Inventory
state: absent
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,33 @@
- name: create a tempdir for hostvars
local_action: shell mktemp -d
register: tempdir
- name: write a file w/ hostvars
local_action:
module: lineinfile
dest: "{{ tempdir.stdout }}/vars"
line: '{"foo": "bar"}'
create: true
- name: Create a Host
tower_host:
name: "some-host"
inventory: "Demo Inventory"
state: present
variables: "@{{ tempdir.stdout }}/vars"
register: result
- assert:
that:
- "result is changed"
- name: Delete a Host
tower_host:
name: "some-host"
inventory: "Demo Inventory"
state: absent
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,21 @@
- name: Create an Inventory
tower_inventory:
name: my-inventory
organization: Default
state: present
register: result
- assert:
that:
- "result is changed"
- name: Delete an Inventory
tower_inventory:
name: my-inventory
organization: Default
state: absent
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,15 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: job
- assert:
that:
- "job is changed"
- "job.status == 'pending'"
- name: Cancel the job
tower_job_cancel:
job_id: "{{ job.id }}"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,11 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: result
- assert:
that:
- "result is changed"
- "result.status == 'pending'"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,20 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: job
- assert:
that:
- "job is changed"
- "job.status == 'pending'"
- name: List jobs w/ a matching primary key
tower_job_list:
query: {"id": "{{ job.id }}"}
register: matching_jobs
- assert:
that:
- "{{ matching_jobs.count }} == 1"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,54 @@
- name: Create an SCM Credential
tower_credential:
name: SCM Credential for JT
organization: Default
kind: scm
- name: Create a Demo Project
tower_project:
name: Job Template Test Project
organization: Default
state: present
scm_type: git
scm_url: https://github.com/ansible/ansible-tower-samples.git
scm_credential: SCM Credential for JT
register: result
- name: Update the project (to clone the git repo)
uri:
url: "https://{{ lookup('env', 'TOWER_HOST') }}/api/v2/projects/{{ result.id }}/update/"
method: POST
user: "{{ lookup('env', 'TOWER_USERNAME') }}"
password: "{{ lookup('env', 'TOWER_PASSWORD') }}"
validate_certs: false
status_code: 202
force_basic_auth: true
- name: Wait for the project to be status=successful
uri:
url: "https://{{ lookup('env', 'TOWER_HOST') }}/api/v2/projects/{{ result.id }}/"
method: GET
user: "{{ lookup('env', 'TOWER_USERNAME') }}"
password: "{{ lookup('env', 'TOWER_PASSWORD') }}"
validate_certs: false
force_basic_auth: true
return_content: true
register: result
until: result.json.status == "successful"
retries: 15
delay: 1
- name: Create a Job Template
tower_job_template:
name: hello-world
project: Job Template Test Project
inventory: Demo Inventory
playbook: hello_world.yml
machine_credential: Demo Credential
job_type: run
state: present
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,16 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: job
- assert:
that:
- "job is changed"
- "job.status == 'pending'"
- name: Wait for the Job to finish
tower_job_wait:
job_id: "{{ job.id }}"
timeout: 60

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,7 @@
- name: Create a Label
tower_label:
name: important
organization: Default
state: present
# TODO: Deleting labels doesn't seem to work currently

View file

@ -1,3 +1,13 @@
- name: confirm Tower version w/ check mode
tower_organization:
name: Default
check_mode: yes
register: result
- assert:
that:
- "result.tower_version == '{{ lookup('env', 'TOWER_VERSION') }}'"
- name: Make sure the default Default organization exists - name: Make sure the default Default organization exists
tower_organization: tower_organization:
name: Default name: Default

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,27 @@
- name: Create an SCM Credential
tower_credential:
name: SCM Credential for Project
organization: Default
kind: scm
- name: Create a Project
tower_project:
name: my-project
organization: Default
state: present
scm_credential: SCM Credential for Project
register: result
- assert:
that:
- "result is changed"
- name: Delete a Project
tower_project:
name: my-project
state: absent
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,39 @@
- name: Create a User
tower_user:
first_name: Joe
last_name: User
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
register: result
- assert:
that:
- "result is changed"
- name: Add Joe to the update role of the default Project
tower_role:
user: joe
role: update
project: Demo Project
state: "{{ item }}"
register: result
with_items:
- "present"
- "absent"
- assert:
that:
- "result is changed"
- name: Delete a User
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"

View file

@ -1,4 +1,33 @@
- name: Attempt to add a Tower team to a non-existant Organization
tower_team:
name: Test Team
organization: Missing Organization
state: present
register: result
ignore_errors: yes
- name: Assert a meaningful error was provided for the failed Tower team creation
assert:
that:
- "'The requested object could not be found.' in result.exception"
- name: Create a Tower team - name: Create a Tower team
tower_team: tower_team:
name: Test Team name: Test Team
organization: Default organization: Default
register: result
- assert:
that:
- "result is changed"
- name: Delete a Tower team
tower_team:
name: Test Team
organization: Default
state: absent
register: result
- assert:
that:
- "result is changed"

View file

@ -0,0 +1,2 @@
cloud/tower
posix/ci/cloud/group4/tower

View file

@ -0,0 +1,76 @@
- name: Create a User
tower_user:
first_name: Joe
last_name: User
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
register: result
- assert:
that:
- "result is changed"
- name: Delete a User
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Create an Auditor
tower_user:
first_name: Joe
last_name: Auditor
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
auditor: true
register: result
- assert:
that:
- "result is changed"
- name: Delete an Auditor
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Create a Superuser
tower_user:
first_name: Joe
last_name: Super
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
superuser: true
register: result
- assert:
that:
- "result is changed"
- name: Delete a Superuser
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"