mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 23:07:42 -02:30
Allow use of credential password prompting with split JTs
also *update test to work with new JT callback call pattern *fix spelling in template
This commit is contained in:
@@ -26,7 +26,7 @@ string of `?all=1` to return all hosts, including disabled ones.
|
|||||||
Specify a query string of `?towervars=1` to add variables
|
Specify a query string of `?towervars=1` to add variables
|
||||||
to the hostvars of each host that specifies its enabled state and database ID.
|
to the hostvars of each host that specifies its enabled state and database ID.
|
||||||
|
|
||||||
Specify a query string of `?subset=shard2of5` to product an inventory that
|
Specify a query string of `?subset=shard2of5` to produce an inventory that
|
||||||
has a restricted number of hosts according to the rules of job splitting.
|
has a restricted number of hosts according to the rules of job splitting.
|
||||||
|
|
||||||
To apply multiple query strings, join them with the `&` character, like `?hostvars=1&all=1`.
|
To apply multiple query strings, join them with the `&` character, like `?hostvars=1&all=1`.
|
||||||
|
|||||||
@@ -342,7 +342,10 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio
|
|||||||
unallowed_fields = set(kwargs.keys()) - set(fields)
|
unallowed_fields = set(kwargs.keys()) - set(fields)
|
||||||
validated_kwargs = kwargs.copy()
|
validated_kwargs = kwargs.copy()
|
||||||
if unallowed_fields:
|
if unallowed_fields:
|
||||||
logger.warn('Fields {} are not allowed as overrides.'.format(unallowed_fields))
|
if parent_field_name is None:
|
||||||
|
logger.warn(six.text_type('Fields {} are not allowed as overrides to spawn {} from {}.').format(
|
||||||
|
six.text_type(', ').join(unallowed_fields), unified_job, self
|
||||||
|
))
|
||||||
map(validated_kwargs.pop, unallowed_fields)
|
map(validated_kwargs.pop, unallowed_fields)
|
||||||
|
|
||||||
unified_job = copy_model_by_class(self, unified_job_class, fields, validated_kwargs)
|
unified_job = copy_model_by_class(self, unified_job_class, fields, validated_kwargs)
|
||||||
|
|||||||
@@ -121,7 +121,11 @@ class TaskManager():
|
|||||||
spawn_node.save()
|
spawn_node.save()
|
||||||
logger.info('Spawned %s in %s for node %s', job.log_format, workflow_job.log_format, spawn_node.pk)
|
logger.info('Spawned %s in %s for node %s', job.log_format, workflow_job.log_format, spawn_node.pk)
|
||||||
if job._resources_sufficient_for_launch():
|
if job._resources_sufficient_for_launch():
|
||||||
can_start = job.signal_start()
|
if workflow_job.start_args:
|
||||||
|
start_args = json.loads(decrypt_field(workflow_job, 'start_args'))
|
||||||
|
else:
|
||||||
|
start_args = {}
|
||||||
|
can_start = job.signal_start(**start_args)
|
||||||
if not can_start:
|
if not can_start:
|
||||||
job.job_explanation = _("Job spawned from workflow could not start because it "
|
job.job_explanation = _("Job spawned from workflow could not start because it "
|
||||||
"was not in the right state or required manual credentials")
|
"was not in the right state or required manual credentials")
|
||||||
@@ -147,7 +151,8 @@ class TaskManager():
|
|||||||
if cancel_finished:
|
if cancel_finished:
|
||||||
logger.info('Marking %s as canceled, all spawned jobs have concluded.', workflow_job.log_format)
|
logger.info('Marking %s as canceled, all spawned jobs have concluded.', workflow_job.log_format)
|
||||||
workflow_job.status = 'canceled'
|
workflow_job.status = 'canceled'
|
||||||
workflow_job.save()
|
workflow_job.start_args = '' # blank field to remove encrypted passwords
|
||||||
|
workflow_job.save(update_fields=['status', 'start_args'])
|
||||||
connection.on_commit(lambda: workflow_job.websocket_emit_status(workflow_job.status))
|
connection.on_commit(lambda: workflow_job.websocket_emit_status(workflow_job.status))
|
||||||
else:
|
else:
|
||||||
is_done, has_failed = dag.is_workflow_done()
|
is_done, has_failed = dag.is_workflow_done()
|
||||||
@@ -155,8 +160,11 @@ class TaskManager():
|
|||||||
continue
|
continue
|
||||||
logger.info('Marking %s as %s.', workflow_job.log_format, 'failed' if has_failed else 'successful')
|
logger.info('Marking %s as %s.', workflow_job.log_format, 'failed' if has_failed else 'successful')
|
||||||
result.append(workflow_job.id)
|
result.append(workflow_job.id)
|
||||||
workflow_job.status = 'failed' if has_failed else 'successful'
|
new_status = 'failed' if has_failed else 'successful'
|
||||||
workflow_job.save()
|
logger.debug(six.text_type("Transitioning {} to {} status.").format(workflow_job.log_format, new_status))
|
||||||
|
workflow_job.status = new_status
|
||||||
|
workflow_job.start_args = '' # blank field to remove encrypted passwords
|
||||||
|
workflow_job.save(update_fields=['status', 'start_args'])
|
||||||
connection.on_commit(lambda: workflow_job.websocket_emit_status(workflow_job.status))
|
connection.on_commit(lambda: workflow_job.websocket_emit_status(workflow_job.status))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import json
|
|||||||
from awx.api.serializers import JobLaunchSerializer
|
from awx.api.serializers import JobLaunchSerializer
|
||||||
from awx.main.models.credential import Credential
|
from awx.main.models.credential import Credential
|
||||||
from awx.main.models.inventory import Inventory, Host
|
from awx.main.models.inventory import Inventory, Host
|
||||||
from awx.main.models.jobs import Job, JobTemplate
|
from awx.main.models.jobs import Job, JobTemplate, UnifiedJobTemplate
|
||||||
|
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
|
|
||||||
@@ -553,15 +553,15 @@ def test_callback_accept_prompted_extra_var(mocker, survey_spec_factory, job_tem
|
|||||||
|
|
||||||
with mocker.patch('awx.main.access.BaseAccess.check_license'):
|
with mocker.patch('awx.main.access.BaseAccess.check_license'):
|
||||||
mock_job = mocker.MagicMock(spec=Job, id=968, extra_vars={"job_launch_var": 3, "survey_var": 4})
|
mock_job = mocker.MagicMock(spec=Job, id=968, extra_vars={"job_launch_var": 3, "survey_var": 4})
|
||||||
with mocker.patch.object(JobTemplate, 'create_unified_job', return_value=mock_job):
|
with mocker.patch.object(UnifiedJobTemplate, 'create_unified_job', return_value=mock_job):
|
||||||
with mocker.patch('awx.api.serializers.JobSerializer.to_representation', return_value={}):
|
with mocker.patch('awx.api.serializers.JobSerializer.to_representation', return_value={}):
|
||||||
with mocker.patch('awx.api.views.JobTemplateCallback.find_matching_hosts', return_value=[host]):
|
with mocker.patch('awx.api.views.JobTemplateCallback.find_matching_hosts', return_value=[host]):
|
||||||
post(
|
post(
|
||||||
reverse('api:job_template_callback', kwargs={'pk': job_template.pk}),
|
reverse('api:job_template_callback', kwargs={'pk': job_template.pk}),
|
||||||
dict(extra_vars={"job_launch_var": 3, "survey_var": 4}, host_config_key="foo"),
|
dict(extra_vars={"job_launch_var": 3, "survey_var": 4}, host_config_key="foo"),
|
||||||
admin_user, expect=201, format='json')
|
admin_user, expect=201, format='json')
|
||||||
assert JobTemplate.create_unified_job.called
|
assert UnifiedJobTemplate.create_unified_job.called
|
||||||
assert JobTemplate.create_unified_job.call_args == ({
|
assert UnifiedJobTemplate.create_unified_job.call_args == ({
|
||||||
'extra_vars': {'survey_var': 4, 'job_launch_var': 3},
|
'extra_vars': {'survey_var': 4, 'job_launch_var': 3},
|
||||||
'_eager_fields': {'launch_type': 'callback'},
|
'_eager_fields': {'launch_type': 'callback'},
|
||||||
'limit': 'single-host'},
|
'limit': 'single-host'},
|
||||||
@@ -579,15 +579,15 @@ def test_callback_ignore_unprompted_extra_var(mocker, survey_spec_factory, job_t
|
|||||||
|
|
||||||
with mocker.patch('awx.main.access.BaseAccess.check_license'):
|
with mocker.patch('awx.main.access.BaseAccess.check_license'):
|
||||||
mock_job = mocker.MagicMock(spec=Job, id=968, extra_vars={"job_launch_var": 3, "survey_var": 4})
|
mock_job = mocker.MagicMock(spec=Job, id=968, extra_vars={"job_launch_var": 3, "survey_var": 4})
|
||||||
with mocker.patch.object(JobTemplate, 'create_unified_job', return_value=mock_job):
|
with mocker.patch.object(UnifiedJobTemplate, 'create_unified_job', return_value=mock_job):
|
||||||
with mocker.patch('awx.api.serializers.JobSerializer.to_representation', return_value={}):
|
with mocker.patch('awx.api.serializers.JobSerializer.to_representation', return_value={}):
|
||||||
with mocker.patch('awx.api.views.JobTemplateCallback.find_matching_hosts', return_value=[host]):
|
with mocker.patch('awx.api.views.JobTemplateCallback.find_matching_hosts', return_value=[host]):
|
||||||
post(
|
post(
|
||||||
reverse('api:job_template_callback', kwargs={'pk':job_template.pk}),
|
reverse('api:job_template_callback', kwargs={'pk':job_template.pk}),
|
||||||
dict(extra_vars={"job_launch_var": 3, "survey_var": 4}, host_config_key="foo"),
|
dict(extra_vars={"job_launch_var": 3, "survey_var": 4}, host_config_key="foo"),
|
||||||
admin_user, expect=201, format='json')
|
admin_user, expect=201, format='json')
|
||||||
assert JobTemplate.create_unified_job.called
|
assert UnifiedJobTemplate.create_unified_job.called
|
||||||
assert JobTemplate.create_unified_job.call_args == ({
|
assert UnifiedJobTemplate.create_unified_job.call_args == ({
|
||||||
'_eager_fields': {'launch_type': 'callback'},
|
'_eager_fields': {'launch_type': 'callback'},
|
||||||
'limit': 'single-host'},
|
'limit': 'single-host'},
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user