mirror of
https://github.com/ansible/awx.git
synced 2026-02-28 16:28:43 -03:30
Merge pull request #5747 from jangsutsr/5728_handle_can_start_without_user_input_cornercase
Handle can_start_without_user_input cornercase
This commit is contained in:
@@ -2678,7 +2678,8 @@ class JobTemplateCallback(GenericAPIView):
|
|||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
extra_vars = None
|
extra_vars = None
|
||||||
if request.content_type == "application/json":
|
# Be careful here: content_type can look like '<content_type>; charset=blar'
|
||||||
|
if request.content_type.startswith("application/json"):
|
||||||
extra_vars = request.data.get("extra_vars", None)
|
extra_vars = request.data.get("extra_vars", None)
|
||||||
# Permission class should have already validated host_config_key.
|
# Permission class should have already validated host_config_key.
|
||||||
job_template = self.get_object()
|
job_template = self.get_object()
|
||||||
@@ -2727,14 +2728,14 @@ class JobTemplateCallback(GenericAPIView):
|
|||||||
return Response(data, status=status.HTTP_400_BAD_REQUEST)
|
return Response(data, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
# Everything is fine; actually create the job.
|
# Everything is fine; actually create the job.
|
||||||
|
kv = {"limit": limit, "launch_type": 'callback'}
|
||||||
|
if extra_vars is not None and job_template.ask_variables_on_launch:
|
||||||
|
kv['extra_vars'] = callback_filter_out_ansible_extra_vars(extra_vars)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
job = job_template.create_job(limit=limit, launch_type='callback')
|
job = job_template.create_job(**kv)
|
||||||
|
|
||||||
# Send a signal to celery that the job should be started.
|
# Send a signal to celery that the job should be started.
|
||||||
kv = {"inventory_sources_already_updated": inventory_sources_already_updated}
|
result = job.signal_start(inventory_sources_already_updated=inventory_sources_already_updated)
|
||||||
if extra_vars is not None:
|
|
||||||
kv['extra_vars'] = callback_filter_out_ansible_extra_vars(extra_vars)
|
|
||||||
result = job.signal_start(**kv)
|
|
||||||
if not result:
|
if not result:
|
||||||
data = dict(msg=_('Error starting job!'))
|
data = dict(msg=_('Error starting job!'))
|
||||||
return Response(data, status=status.HTTP_400_BAD_REQUEST)
|
return Response(data, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|||||||
@@ -310,9 +310,13 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour
|
|||||||
elif self.variables_needed_to_start:
|
elif self.variables_needed_to_start:
|
||||||
variables_needed = True
|
variables_needed = True
|
||||||
prompting_needed = False
|
prompting_needed = False
|
||||||
for value in self._ask_for_vars_dict().values():
|
# The behavior of provisioning callback should mimic
|
||||||
if value:
|
# that of job template launch, so prompting_needed should
|
||||||
prompting_needed = True
|
# not block a provisioning callback from creating/launching jobs.
|
||||||
|
if callback_extra_vars is None:
|
||||||
|
for value in self._ask_for_vars_dict().values():
|
||||||
|
if value:
|
||||||
|
prompting_needed = True
|
||||||
return (not prompting_needed and
|
return (not prompting_needed and
|
||||||
not self.passwords_needed_to_start and
|
not self.passwords_needed_to_start and
|
||||||
not variables_needed)
|
not variables_needed)
|
||||||
@@ -1139,7 +1143,7 @@ class JobEvent(CreatedModifiedModel):
|
|||||||
# Save artifact data to parent job (if provided).
|
# Save artifact data to parent job (if provided).
|
||||||
if artifact_dict:
|
if artifact_dict:
|
||||||
if event_data and isinstance(event_data, dict):
|
if event_data and isinstance(event_data, dict):
|
||||||
# Note: Core has not added support for marking artifacts as
|
# Note: Core has not added support for marking artifacts as
|
||||||
# sensitive yet. Going forward, core will not use
|
# sensitive yet. Going forward, core will not use
|
||||||
# _ansible_no_log to denote sensitive set_stats calls.
|
# _ansible_no_log to denote sensitive set_stats calls.
|
||||||
# Instead, they plan to add a flag outside of the traditional
|
# Instead, they plan to add a flag outside of the traditional
|
||||||
|
|||||||
@@ -344,3 +344,53 @@ def test_job_launch_unprompted_vars_with_survey(mocker, survey_spec_factory, job
|
|||||||
|
|
||||||
# Check that the survey variable is accepted and the job variable isn't
|
# Check that the survey variable is accepted and the job variable isn't
|
||||||
mock_job.signal_start.assert_called_once()
|
mock_job.signal_start.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@pytest.mark.job_runtime_vars
|
||||||
|
def test_callback_accept_prompted_extra_var(mocker, survey_spec_factory, job_template_prompts, post, admin_user, host):
|
||||||
|
job_template = job_template_prompts(True)
|
||||||
|
job_template.host_config_key = "foo"
|
||||||
|
job_template.survey_enabled = True
|
||||||
|
job_template.survey_spec = survey_spec_factory('survey_var')
|
||||||
|
job_template.save()
|
||||||
|
|
||||||
|
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})
|
||||||
|
with mocker.patch.object(JobTemplate, 'create_unified_job', return_value=mock_job):
|
||||||
|
with mocker.patch('awx.api.serializers.JobSerializer.to_representation', return_value={}):
|
||||||
|
with mocker.patch('awx.api.views.JobTemplateCallback.find_matching_hosts', return_value=[host]):
|
||||||
|
post(
|
||||||
|
reverse('api:job_template_callback', args=[job_template.pk]),
|
||||||
|
dict(extra_vars={"job_launch_var": 3, "survey_var": 4}, host_config_key="foo"),
|
||||||
|
admin_user, expect=201, format='json')
|
||||||
|
assert JobTemplate.create_unified_job.called
|
||||||
|
assert JobTemplate.create_unified_job.call_args == ({'extra_vars': {'survey_var': 4,
|
||||||
|
'job_launch_var': 3},
|
||||||
|
'launch_type': 'callback',
|
||||||
|
'limit': 'single-host'},)
|
||||||
|
|
||||||
|
mock_job.signal_start.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@pytest.mark.job_runtime_vars
|
||||||
|
def test_callback_ignore_unprompted_extra_var(mocker, survey_spec_factory, job_template_prompts, post, admin_user, host):
|
||||||
|
job_template = job_template_prompts(False)
|
||||||
|
job_template.host_config_key = "foo"
|
||||||
|
job_template.save()
|
||||||
|
|
||||||
|
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})
|
||||||
|
with mocker.patch.object(JobTemplate, 'create_unified_job', return_value=mock_job):
|
||||||
|
with mocker.patch('awx.api.serializers.JobSerializer.to_representation', return_value={}):
|
||||||
|
with mocker.patch('awx.api.views.JobTemplateCallback.find_matching_hosts', return_value=[host]):
|
||||||
|
post(
|
||||||
|
reverse('api:job_template_callback', args=[job_template.pk]),
|
||||||
|
dict(extra_vars={"job_launch_var": 3, "survey_var": 4}, host_config_key="foo"),
|
||||||
|
admin_user, expect=201, format='json')
|
||||||
|
assert JobTemplate.create_unified_job.called
|
||||||
|
assert JobTemplate.create_unified_job.call_args == ({'launch_type': 'callback',
|
||||||
|
'limit': 'single-host'},)
|
||||||
|
|
||||||
|
mock_job.signal_start.assert_called_once()
|
||||||
|
|||||||
@@ -115,3 +115,16 @@ def test_job_template_survey_mixin_length(job_template_factory):
|
|||||||
{'type':'password', 'variable':'my_other_variable'}]}
|
{'type':'password', 'variable':'my_other_variable'}]}
|
||||||
kwargs = obj._update_unified_job_kwargs(extra_vars={'my_variable':'$encrypted$'})
|
kwargs = obj._update_unified_job_kwargs(extra_vars={'my_variable':'$encrypted$'})
|
||||||
assert kwargs['extra_vars'] == '{"my_variable": "my_default"}'
|
assert kwargs['extra_vars'] == '{"my_variable": "my_default"}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_job_template_can_start_with_callback_extra_vars_provided(job_template_factory):
|
||||||
|
objects = job_template_factory(
|
||||||
|
'callback_extra_vars_test',
|
||||||
|
organization='org1',
|
||||||
|
inventory='inventory1',
|
||||||
|
credential='cred1',
|
||||||
|
persisted=False,
|
||||||
|
)
|
||||||
|
obj = objects.job_template
|
||||||
|
obj.ask_variables_on_launch = True
|
||||||
|
assert obj.can_start_without_user_input(callback_extra_vars='{"foo": "bar"}') is True
|
||||||
|
|||||||
Reference in New Issue
Block a user