Add workflow node identifier

Generate new modules WFJT and WFJT node
Touch up generated syntax, test new modules

Add utility method in awxkit

Fix some issues with non-name identifier in
  AWX collection module_utils

Update workflow docs for workflow node identifier

Test and fix WFJT modules survey_spec
Plug in survey spec for the new module
Handle survey spec idempotency and test

add associations for node connections
Handle node credential prompts as well

Add indexes for new identifier field

Test with unicode dragon in name
This commit is contained in:
AlanCoding
2020-03-13 23:05:01 -04:00
parent d941f11ccd
commit 5e595caf5e
16 changed files with 879 additions and 40 deletions

View File

@@ -164,6 +164,24 @@ def run_module(request, collection_import):
return rf
@pytest.fixture
def survey_spec():
return {
"spec": [
{
"index": 0,
"question_name": "my question?",
"default": "mydef",
"variable": "myvar",
"type": "text",
"required": False
}
],
"description": "test",
"name": "test"
}
@pytest.fixture
def organization():
return Organization.objects.create(name='Default')

View File

@@ -0,0 +1,62 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import pytest
from awx.main.models import WorkflowJobTemplate
@pytest.mark.django_db
def test_create_workflow_job_template(run_module, admin_user, organization, survey_spec):
result = run_module('tower_workflow_job_template', {
'name': 'foo-workflow',
'organization': organization.name,
'extra_vars': {'foo': 'bar', 'another-foo': {'barz': 'bar2'}},
'survey': survey_spec,
'survey_enabled': True,
'state': 'present'
}, admin_user)
assert not result.get('failed', False), result.get('msg', result)
wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow')
assert wfjt.extra_vars == '{"foo": "bar", "another-foo": {"barz": "bar2"}}'
result.pop('invocation', None)
assert result == {
"name": "foo-workflow",
"id": wfjt.id,
"changed": True
}
assert wfjt.organization_id == organization.id
assert wfjt.survey_spec == survey_spec
@pytest.mark.django_db
def test_survey_spec_only_changed(run_module, admin_user, organization, survey_spec):
wfjt = WorkflowJobTemplate.objects.create(
organization=organization, name='foo-workflow',
survey_enabled=True, survey_spec=survey_spec
)
result = run_module('tower_workflow_job_template', {
'name': 'foo-workflow',
'organization': organization.name,
'state': 'present'
}, admin_user)
assert not result.get('failed', False), result.get('msg', result)
assert not result.get('changed', True), result
wfjt.refresh_from_db()
assert wfjt.survey_spec == survey_spec
survey_spec['description'] = 'changed description'
result = run_module('tower_workflow_job_template', {
'name': 'foo-workflow',
'organization': organization.name,
'survey': survey_spec,
'state': 'present'
}, admin_user)
assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result
wfjt.refresh_from_db()
assert wfjt.survey_spec == survey_spec

View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import pytest
from awx.main.models import WorkflowJobTemplateNode, WorkflowJobTemplate, JobTemplate
@pytest.fixture
def job_template(project, inventory):
return JobTemplate.objects.create(
project=project,
inventory=inventory,
playbook='helloworld.yml',
name='foo-jt',
ask_variables_on_launch=True,
ask_credential_on_launch=True,
ask_limit_on_launch=True
)
@pytest.fixture
def wfjt(organization):
WorkflowJobTemplate.objects.create(organization=None, name='foo-workflow') # to test org scoping
return WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow')
@pytest.mark.django_db
def test_create_workflow_job_template_node(run_module, admin_user, wfjt, job_template):
this_identifier = '42🐉'
result = run_module('tower_workflow_job_template_node', {
'identifier': this_identifier,
'workflow_job_template': 'foo-workflow',
'organization': wfjt.organization.name,
'unified_job_template': 'foo-jt',
'state': 'present'
}, admin_user)
assert not result.get('failed', False), result.get('msg', result)
node = WorkflowJobTemplateNode.objects.get(identifier=this_identifier)
result.pop('invocation', None)
assert result == {
"name": this_identifier, # FIXME: should this be identifier instead
"id": node.id,
"changed": True
}
assert node.workflow_job_template_id == wfjt.id
assert node.unified_job_template_id == job_template.id
@pytest.mark.django_db
def test_make_use_of_prompts(run_module, admin_user, wfjt, job_template, machine_credential, vault_credential):
# Create to temporarily woraround other issue https://github.com/ansible/awx/issues/5177
WorkflowJobTemplateNode.objects.create(
identifier='42', workflow_job_template=wfjt, unified_job_template=job_template)
result = run_module('tower_workflow_job_template_node', {
'identifier': '42',
'workflow_job_template': 'foo-workflow',
'organization': wfjt.organization.name,
'unified_job_template': 'foo-jt',
'extra_data': {'foo': 'bar', 'another-foo': {'barz': 'bar2'}},
'limit': 'foo_hosts',
'credentials': [machine_credential.name, vault_credential.name],
'state': 'present'
}, admin_user)
assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', False)
node = WorkflowJobTemplateNode.objects.get(identifier='42')
assert node.limit == 'foo_hosts'
assert node.extra_data == {'foo': 'bar', 'another-foo': {'barz': 'bar2'}}
assert set(node.credentials.all()) == set([machine_credential, vault_credential])
@pytest.mark.django_db
def test_create_with_edges(run_module, admin_user, wfjt, job_template):
next_nodes = [
WorkflowJobTemplateNode.objects.create(
identifier='foo{0}'.format(i),
workflow_job_template=wfjt,
unified_job_template=job_template
) for i in range(3)
]
# Create to temporarily woraround other issue https://github.com/ansible/awx/issues/5177
WorkflowJobTemplateNode.objects.create(
identifier='42', workflow_job_template=wfjt, unified_job_template=job_template)
result = run_module('tower_workflow_job_template_node', {
'identifier': '42',
'workflow_job_template': 'foo-workflow',
'organization': wfjt.organization.name,
'unified_job_template': 'foo-jt',
'success_nodes': ['foo0'],
'always_nodes': ['foo1'],
'failure_nodes': ['foo2'],
'state': 'present'
}, admin_user)
assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', False)
node = WorkflowJobTemplateNode.objects.get(identifier='42')
assert list(node.success_nodes.all()) == [next_nodes[0]]
assert list(node.always_nodes.all()) == [next_nodes[1]]
assert list(node.failure_nodes.all()) == [next_nodes[2]]

View File

@@ -10,32 +10,29 @@ from awx.main.models import (
@pytest.mark.django_db
def test_create_workflow_job_template(run_module, admin_user, organization, silence_deprecation):
module_args = {
def test_create_workflow_job_template(run_module, admin_user, organization, survey_spec, silence_deprecation):
result = run_module('tower_workflow_template', {
'name': 'foo-workflow',
'organization': organization.name,
'extra_vars': {'foo': 'bar', 'another-foo': {'barz': 'bar2'}},
'survey': survey_spec,
'survey_enabled': True,
'state': 'present'
}
result = run_module('tower_workflow_template', module_args, admin_user)
}, admin_user)
wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow')
assert wfjt.extra_vars == '{"foo": "bar", "another-foo": {"barz": "bar2"}}'
result.pop('module_args', None)
result.pop('invocation', None)
assert result == {
"workflow_template": "foo-workflow", # TODO: remove after refactor
"state": "present",
"id": wfjt.id,
"changed": True,
"invocation": {
"module_args": module_args
}
"changed": True
}
assert wfjt.organization_id == organization.id
assert wfjt.survey_spec == survey_spec
@pytest.mark.django_db