diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 3960790ce7..236ece70e8 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -2756,16 +2756,11 @@ class JobOptionsSerializer(LabelsListMixin, BaseSerializer): if obj.organization_id: res['organization'] = self.reverse('api:organization_detail', kwargs={'pk': obj.organization_id}) if isinstance(obj, UnifiedJobTemplate): - res['extra_credentials'] = self.reverse( - 'api:job_template_extra_credentials_list', - kwargs={'pk': obj.pk} - ) res['credentials'] = self.reverse( 'api:job_template_credentials_list', kwargs={'pk': obj.pk} ) elif isinstance(obj, UnifiedJob): - res['extra_credentials'] = self.reverse('api:job_extra_credentials_list', kwargs={'pk': obj.pk}) res['credentials'] = self.reverse('api:job_credentials_list', kwargs={'pk': obj.pk}) return res @@ -2934,7 +2929,6 @@ class JobTemplateSerializer(JobTemplateMixin, UnifiedJobTemplateSerializer, JobO summary_fields = super(JobTemplateSerializer, self).get_summary_fields(obj) all_creds = [] # Organize credential data into multitude of deprecated fields - extra_creds = [] if obj.pk: for cred in obj.credentials.all(): summarized_cred = { @@ -2945,10 +2939,6 @@ class JobTemplateSerializer(JobTemplateMixin, UnifiedJobTemplateSerializer, JobO 'cloud': cred.credential_type.kind == 'cloud' } all_creds.append(summarized_cred) - if cred.credential_type.kind in ('cloud', 'net'): - extra_creds.append(summarized_cred) - if self.is_detail_view: - summary_fields['extra_credentials'] = extra_creds summary_fields['credentials'] = all_creds return summary_fields @@ -3023,7 +3013,6 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer): summary_fields = super(JobSerializer, self).get_summary_fields(obj) all_creds = [] # Organize credential data into multitude of deprecated fields - extra_creds = [] if obj.pk: for cred in obj.credentials.all(): summarized_cred = { @@ -3034,10 +3023,6 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer): 'cloud': cred.credential_type.kind == 'cloud' } all_creds.append(summarized_cred) - if cred.credential_type.kind in ('cloud', 'net'): - extra_creds.append(summarized_cred) - if self.is_detail_view: - summary_fields['extra_credentials'] = extra_creds summary_fields['credentials'] = all_creds return summary_fields diff --git a/awx/api/urls/urls.py b/awx/api/urls/urls.py index ac1182ddca..2745f87095 100644 --- a/awx/api/urls/urls.py +++ b/awx/api/urls/urls.py @@ -23,9 +23,7 @@ from awx.api.views import ( UnifiedJobList, HostAnsibleFactsDetail, JobCredentialsList, - JobExtraCredentialsList, JobTemplateCredentialsList, - JobTemplateExtraCredentialsList, SchedulePreview, ScheduleZoneInfo, OAuth2ApplicationList, @@ -83,9 +81,7 @@ v2_urls = [ url(r'^credential_types/', include(credential_type_urls)), url(r'^credential_input_sources/', include(credential_input_source_urls)), url(r'^hosts/(?P[0-9]+)/ansible_facts/$', HostAnsibleFactsDetail.as_view(), name='host_ansible_facts_detail'), - url(r'^jobs/(?P[0-9]+)/extra_credentials/$', JobExtraCredentialsList.as_view(), name='job_extra_credentials_list'), url(r'^jobs/(?P[0-9]+)/credentials/$', JobCredentialsList.as_view(), name='job_credentials_list'), - url(r'^job_templates/(?P[0-9]+)/extra_credentials/$', JobTemplateExtraCredentialsList.as_view(), name='job_template_extra_credentials_list'), url(r'^job_templates/(?P[0-9]+)/credentials/$', JobTemplateCredentialsList.as_view(), name='job_template_credentials_list'), url(r'^schedules/preview/$', SchedulePreview.as_view(), name='schedule_rrule'), url(r'^schedules/zoneinfo/$', ScheduleZoneInfo.as_view(), name='schedule_zoneinfo'), diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index aca8d892a0..1e215d653f 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -12,7 +12,7 @@ import socket import sys import time from base64 import b64encode -from collections import OrderedDict, Iterable +from collections import OrderedDict # Django @@ -2344,51 +2344,6 @@ class JobTemplateLaunch(RetrieveAPIView): if 'inventory' not in modern_data and id_fd in modern_data: modern_data['inventory'] = modern_data[id_fd] - # Automatically convert legacy launch credential arguments into a list of `.credentials` - if 'credentials' in modern_data and 'extra_credentials' in modern_data: - raise ParseError({"error": _( - "'credentials' cannot be used in combination with 'extra_credentials'." - )}) - - if 'extra_credentials' in modern_data: - # make a list of the current credentials - existing_credentials = obj.credentials.all() - template_credentials = list(existing_credentials) # save copy of existing - new_credentials = [] - if 'extra_credentials' in modern_data: - existing_credentials = [ - cred for cred in existing_credentials - if cred.credential_type.kind not in ('cloud', 'net') - ] - prompted_value = modern_data.pop('extra_credentials') - - # validate type, since these are not covered by a serializer - if not isinstance(prompted_value, Iterable): - msg = _( - "Incorrect type. Expected a list received {}." - ).format(prompted_value.__class__.__name__) - raise ParseError({'extra_credentials': [msg], 'credentials': [msg]}) - - # add the deprecated credential specified in the request - if not isinstance(prompted_value, Iterable) or isinstance(prompted_value, str): - prompted_value = [prompted_value] - - # If user gave extra_credentials, special case to use exactly - # the given list without merging with JT credentials - if prompted_value: - obj._deprecated_credential_launch = True # signal to not merge credentials - new_credentials.extend(prompted_value) - - # combine the list of "new" and the filtered list of "old" - new_credentials.extend([cred.pk for cred in existing_credentials]) - if new_credentials: - # If provided list doesn't contain the pre-existing credentials - # defined on the template, add them back here - for cred_obj in template_credentials: - if cred_obj.pk not in new_credentials: - new_credentials.append(cred_obj.pk) - modern_data['credentials'] = new_credentials - # credential passwords were historically provided as top-level attributes if 'credential_passwords' not in modern_data: modern_data['credential_passwords'] = data.copy() @@ -2711,22 +2666,6 @@ class JobTemplateCredentialsList(SubListCreateAttachDetachAPIView): return super(JobTemplateCredentialsList, self).is_valid_relation(parent, sub, created) -class JobTemplateExtraCredentialsList(JobTemplateCredentialsList): - - deprecated = True - - def get_queryset(self): - sublist_qs = super(JobTemplateExtraCredentialsList, self).get_queryset() - sublist_qs = sublist_qs.filter(credential_type__kind__in=['cloud', 'net']) - return sublist_qs - - def is_valid_relation(self, parent, sub, created=False): - valid = super(JobTemplateExtraCredentialsList, self).is_valid_relation(parent, sub, created) - if sub.credential_type.kind not in ('cloud', 'net'): - return {'error': _('Extra credentials must be network or cloud.')} - return valid - - class JobTemplateLabelList(DeleteLastUnattachLabelMixin, SubListCreateAttachDetachAPIView): model = models.Label @@ -3543,16 +3482,6 @@ class JobCredentialsList(SubListAPIView): relationship = 'credentials' -class JobExtraCredentialsList(JobCredentialsList): - - deprecated = True - - def get_queryset(self): - sublist_qs = super(JobExtraCredentialsList, self).get_queryset() - sublist_qs = sublist_qs.filter(credential_type__kind__in=['cloud', 'net']) - return sublist_qs - - class JobLabelList(SubListAPIView): model = models.Label diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index e67478a8e8..1ecb788900 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -439,13 +439,9 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour field = self._meta.get_field(field_name) if isinstance(field, models.ManyToManyField): old_value = set(old_value.all()) - if getattr(self, '_deprecated_credential_launch', False): - # TODO: remove this code branch when support for `extra_credentials` goes away - new_value = set(kwargs[field_name]) - else: - new_value = set(kwargs[field_name]) - old_value - if not new_value: - continue + new_value = set(kwargs[field_name]) - old_value + if not new_value: + continue if new_value == old_value: # no-op case: Fields the same as template's value diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 70fd0e004d..1e6d549e80 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -413,9 +413,8 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio if 'extra_vars' in validated_kwargs: unified_job.handle_extra_data(validated_kwargs['extra_vars']) - if not getattr(self, '_deprecated_credential_launch', False): - # Create record of provided prompts for relaunch and rescheduling - unified_job.create_config_from_prompts(kwargs, parent=self) + # Create record of provided prompts for relaunch and rescheduling + unified_job.create_config_from_prompts(kwargs, parent=self) # manually issue the create activity stream entry _after_ M2M relations # have been associated to the UJ diff --git a/awx/main/tests/docs/test_swagger_generation.py b/awx/main/tests/docs/test_swagger_generation.py index 5ee30e0b1e..806382158f 100644 --- a/awx/main/tests/docs/test_swagger_generation.py +++ b/awx/main/tests/docs/test_swagger_generation.py @@ -105,9 +105,6 @@ class TestSwaggerGeneration(): 'get', 'put', 'patch', 'delete' ] - # Test deprecated paths - assert paths['/api/v2/jobs/{id}/extra_credentials/']['get']['deprecated'] is True - @pytest.mark.parametrize('path', [ '/api/', '/api/v2/', diff --git a/awx/main/tests/functional/api/test_deprecated_credential_assignment.py b/awx/main/tests/functional/api/test_deprecated_credential_assignment.py index 880b7ff892..38fea20c4d 100644 --- a/awx/main/tests/functional/api/test_deprecated_credential_assignment.py +++ b/awx/main/tests/functional/api/test_deprecated_credential_assignment.py @@ -24,41 +24,6 @@ def job_template(job_template, project, inventory): return job_template -@pytest.mark.django_db -def test_extra_credentials_filtering(get, job_template, admin, - machine_credential, vault_credential, credential): - job_template.credentials.add(machine_credential) - job_template.credentials.add(vault_credential) - job_template.credentials.add(credential) - url = reverse( - 'api:job_template_extra_credentials_list', - kwargs={'pk': job_template.pk} - ) - resp = get(url, admin, expect=200) - assert resp.data['count'] == 1 - assert resp.data['results'][0]['id'] == credential.pk - - -@pytest.mark.django_db -def test_extra_credentials_requires_cloud_or_net(get, post, job_template, admin, - machine_credential, vault_credential, credential, - net_credential): - url = reverse( - 'api:job_template_extra_credentials_list', - kwargs={'pk': job_template.pk} - ) - - for cred in (machine_credential, vault_credential): - resp = post(url, {'associate': True, 'id': cred.pk}, admin, expect=400) - assert 'Extra credentials must be network or cloud.' in smart_str(resp.content) - - post(url, {'associate': True, 'id': credential.pk}, admin, expect=204) - assert get(url, admin).data['count'] == 1 - - post(url, {'associate': True, 'id': net_credential.pk}, admin, expect=204) - assert get(url, admin).data['count'] == 2 - - @pytest.mark.django_db def test_prevent_multiple_machine_creds(get, post, job_template, admin, machine_credential): url = reverse( @@ -115,52 +80,6 @@ def test_prevent_multiple_machine_creds_at_launch(get, post, job_template, admin assert 'Cannot assign multiple Machine credentials.' in smart_str(resp.content) -@pytest.mark.django_db -def test_extra_credentials_unique_by_kind(get, post, job_template, admin, - credentialtype_aws): - url = reverse( - 'api:job_template_extra_credentials_list', - kwargs={'pk': job_template.pk} - ) - - def _new_cred(name): - return { - 'name': name, - 'credential_type': credentialtype_aws.pk, - 'inputs': { - 'username': 'bob', - 'password': 'secret', - } - } - - post(url, _new_cred('First Cred'), admin, expect=201) - assert get(url, admin).data['count'] == 1 - - resp = post(url, _new_cred('Second Cred'), admin, expect=400) - assert 'Cannot assign multiple Amazon Web Services credentials.' in smart_str(resp.content) - - -@pytest.mark.django_db -def test_extra_credentials_at_launch(get, post, job_template, admin, credential): - url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk}) - pk = post(url, {'extra_credentials': [credential.pk]}, admin, expect=201).data['job'] - summary_fields = get(reverse('api:job_detail', kwargs={'pk': pk}), admin).data['summary_fields'] - - assert len(summary_fields['credentials']) == 1 - - -@pytest.mark.django_db -def test_modify_extra_credentials_at_launch(get, post, job_template, admin, - machine_credential, vault_credential, credential): - job_template.credentials.add(machine_credential) - job_template.credentials.add(vault_credential) - url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk}) - pk = post(url, {'extra_credentials': [credential.pk]}, admin, expect=201).data['job'] - - summary_fields = get(reverse('api:job_detail', kwargs={'pk': pk}), admin).data['summary_fields'] - assert len(summary_fields['credentials']) == 3 - - @pytest.mark.django_db def test_ssh_password_prompted_at_launch(get, post, job_template, admin, machine_credential): job_template.credentials.add(machine_credential) @@ -229,25 +148,6 @@ def test_vault_credential_with_password_at_launch(get, post, job_template, admin signal_start.assert_called_with(vault_password='testing123') -@pytest.mark.django_db -def test_extra_creds_prompted_at_launch(get, post, job_template, admin, net_credential): - url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk}) - resp = post(url, {'extra_credentials': [net_credential.pk]}, admin, expect=201) - - summary_fields = get( - reverse('api:job_detail', kwargs={'pk': resp.data['job']}), - admin - ).data['summary_fields'] - assert len(summary_fields['credentials']) == 1 - - -@pytest.mark.django_db -def test_invalid_mixed_credentials_specification(get, post, job_template, admin, net_credential): - url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk}) - post(url=url, data={'credentials': [net_credential.pk], 'extra_credentials': [net_credential.pk]}, - user=admin, expect=400) - - @pytest.mark.django_db def test_deprecated_credential_activity_stream(patch, admin_user, machine_credential, job_template): job_template.credentials.add(machine_credential) diff --git a/awx/main/tests/functional/api/test_job.py b/awx/main/tests/functional/api/test_job.py index db32c0dd7f..a0467bd6c0 100644 --- a/awx/main/tests/functional/api/test_job.py +++ b/awx/main/tests/functional/api/test_job.py @@ -22,20 +22,6 @@ from awx.main.models import ( ) -@pytest.mark.django_db -def test_extra_credentials(get, organization_factory, job_template_factory, credential): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - jt.credentials.add(credential) - jt.save() - job = jt.create_unified_job() - - url = reverse('api:job_extra_credentials_list', kwargs={'pk': job.pk}) - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 1 - - @pytest.mark.django_db def test_job_relaunch_permission_denied_response( post, get, inventory, project, credential, net_credential, machine_credential): @@ -50,7 +36,7 @@ def test_job_relaunch_permission_denied_response( r = get(job.get_absolute_url(), jt_user, expect=200) assert r.data['summary_fields']['user_capabilities']['start'] - # Job has prompted extra_credential, launch denied w/ message + # Job has prompted credential, launch denied w/ message job.launch_config.credentials.add(net_credential) r = post(reverse('api:job_relaunch', kwargs={'pk':job.pk}), {}, jt_user, expect=403) assert 'launched with prompted fields you do not have access to' in r.data['detail'] @@ -70,7 +56,7 @@ def test_job_relaunch_prompts_not_accepted_response( r = get(job.get_absolute_url(), jt_user, expect=200) assert r.data['summary_fields']['user_capabilities']['start'] - # Job has prompted extra_credential, launch denied w/ message + # Job has prompted credential, launch denied w/ message job.launch_config.credentials.add(net_credential) r = post(reverse('api:job_relaunch', kwargs={'pk':job.pk}), {}, jt_user, expect=403) diff --git a/awx/main/tests/functional/api/test_job_runtime_params.py b/awx/main/tests/functional/api/test_job_runtime_params.py index 4d86b8dd07..d792ec656d 100644 --- a/awx/main/tests/functional/api/test_job_runtime_params.py +++ b/awx/main/tests/functional/api/test_job_runtime_params.py @@ -304,7 +304,7 @@ def test_job_launch_with_default_creds(machine_credential, vault_credential, dep @pytest.mark.django_db def test_job_launch_JT_enforces_unique_credentials_kinds(machine_credential, credentialtype_aws, deploy_jobtemplate): """ - JT launching should require that extra_credentials have distinct CredentialTypes + JT launching should require that credentials have distinct CredentialTypes """ creds = [] for i in range(2): diff --git a/awx/main/tests/functional/api/test_job_template.py b/awx/main/tests/functional/api/test_job_template.py index 6ad0271042..1883f6e6ec 100644 --- a/awx/main/tests/functional/api/test_job_template.py +++ b/awx/main/tests/functional/api/test_job_template.py @@ -45,27 +45,6 @@ def test_create(post, project, machine_credential, inventory, alice, grant_proje ) -@pytest.mark.django_db -def test_extra_credential_creation(get, post, organization_factory, job_template_factory, credentialtype_aws): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - - url = reverse('api:job_template_extra_credentials_list', kwargs={'pk': jt.pk}) - response = post(url, { - 'name': 'My Cred', - 'credential_type': credentialtype_aws.pk, - 'inputs': { - 'username': 'bob', - 'password': 'secret', - } - }, objs.superusers.admin) - assert response.status_code == 201 - - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 1 - - @pytest.mark.django_db @pytest.mark.parametrize('kind', ['scm', 'insights']) def test_invalid_credential_kind_xfail(get, post, organization_factory, job_template_factory, kind): @@ -87,42 +66,6 @@ def test_invalid_credential_kind_xfail(get, post, organization_factory, job_temp assert 'Cannot assign a Credential of kind `{}`.'.format(kind) in response.data.values() -@pytest.mark.django_db -def test_extra_credential_unique_type_xfail(get, post, organization_factory, job_template_factory, credentialtype_aws): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - - url = reverse('api:job_template_extra_credentials_list', kwargs={'pk': jt.pk}) - response = post(url, { - 'name': 'My Cred', - 'credential_type': credentialtype_aws.pk, - 'inputs': { - 'username': 'bob', - 'password': 'secret', - } - }, objs.superusers.admin) - assert response.status_code == 201 - - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 1 - - # this request should fail because you can't assign the same type (aws) - # twice - response = post(url, { - 'name': 'My Cred', - 'credential_type': credentialtype_aws.pk, - 'inputs': { - 'username': 'joe', - 'password': 'another-secret', - } - }, objs.superusers.admin) - assert response.status_code == 400 - - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 1 - - @pytest.mark.django_db def test_create_with_forks_exceeding_maximum_xfail(alice, post, project, inventory, settings): project.use_role.members.add(alice) @@ -143,60 +86,6 @@ def test_create_with_forks_exceeding_maximum_xfail(alice, post, project, invento assert 'Maximum number of forks (10) exceeded' in str(response.data) -@pytest.mark.django_db -def test_attach_extra_credential(get, post, organization_factory, job_template_factory, credential): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - - url = reverse('api:job_template_extra_credentials_list', kwargs={'pk': jt.pk}) - response = post(url, { - 'associate': True, - 'id': credential.id, - }, objs.superusers.admin) - assert response.status_code == 204 - - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 1 - - -@pytest.mark.django_db -def test_detach_extra_credential(get, post, organization_factory, job_template_factory, credential): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - jt.credentials.add(credential) - jt.save() - - url = reverse('api:job_template_extra_credentials_list', kwargs={'pk': jt.pk}) - response = post(url, { - 'disassociate': True, - 'id': credential.id, - }, objs.superusers.admin) - assert response.status_code == 204 - - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 0 - - -@pytest.mark.django_db -def test_attach_extra_credential_wrong_kind_xfail(get, post, organization_factory, job_template_factory, machine_credential): - """Extra credentials only allow net + cloud credentials""" - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - - url = reverse('api:job_template_extra_credentials_list', kwargs={'pk': jt.pk}) - response = post(url, { - 'associate': True, - 'id': machine_credential.id, - }, objs.superusers.admin) - assert response.status_code == 400 - - response = get(url, user=objs.superusers.admin) - assert response.data.get('count') == 0 - - @pytest.mark.django_db @pytest.mark.parametrize( "grant_project, grant_inventory, expect", [ @@ -368,57 +257,6 @@ def test_launch_with_pending_deletion_inventory_workflow(get, post, organization assert resp.data['inventory'] == ['The inventory associated with this Workflow is being deleted.'] -@pytest.mark.django_db -def test_launch_with_extra_credentials(get, post, organization_factory, - job_template_factory, machine_credential, - credential, net_credential): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - jt.ask_credential_on_launch = True - jt.save() - - resp = post( - reverse('api:job_template_launch', kwargs={'pk': jt.pk}), - dict( - credentials=[machine_credential.pk, credential.pk, net_credential.pk] - ), - objs.superusers.admin, expect=201 - ) - job_pk = resp.data.get('id') - - resp = get(reverse('api:job_extra_credentials_list', kwargs={'pk': job_pk}), objs.superusers.admin) - assert resp.data.get('count') == 2 - - resp = get(reverse('api:job_template_extra_credentials_list', kwargs={'pk': jt.pk}), objs.superusers.admin) - assert resp.data.get('count') == 0 - - -@pytest.mark.django_db -def test_launch_with_extra_credentials_not_allowed(get, post, organization_factory, - job_template_factory, machine_credential, - credential, net_credential): - objs = organization_factory("org", superusers=['admin']) - jt = job_template_factory("jt", organization=objs.organization, - inventory='test_inv', project='test_proj').job_template - jt.credentials.add(machine_credential) - jt.ask_credential_on_launch = False - jt.save() - - resp = post( - reverse('api:job_template_launch', kwargs={'pk': jt.pk}), - dict( - credentials=[machine_credential.pk, credential.pk, net_credential.pk] - ), - objs.superusers.admin - ) - assert 'credentials' in resp.data['ignored_fields'].keys() - job_pk = resp.data.get('id') - - resp = get(reverse('api:job_extra_credentials_list', kwargs={'pk': job_pk}), objs.superusers.admin) - assert resp.data.get('count') == 0 - - @pytest.mark.django_db def test_jt_without_project(inventory): data = dict(name="Test", job_type="run", diff --git a/awx/main/tests/functional/test_rbac_job_templates.py b/awx/main/tests/functional/test_rbac_job_templates.py index 0cbd8bcbc6..99dc1e22ce 100644 --- a/awx/main/tests/functional/test_rbac_job_templates.py +++ b/awx/main/tests/functional/test_rbac_job_templates.py @@ -128,7 +128,7 @@ def test_job_template_access_admin(role_names, jt_linked, rando): @pytest.mark.django_db -def test_job_template_extra_credentials_prompts_access( +def test_job_template_credentials_prompts_access( rando, post, inventory, project, machine_credential, vault_credential): jt = JobTemplate.objects.create( name = 'test-jt', @@ -149,14 +149,14 @@ def test_job_template_extra_credentials_prompts_access( @pytest.mark.django_db class TestJobTemplateCredentials: - def test_job_template_cannot_add_extra_credentials(self, job_template, credential, rando): + def test_job_template_cannot_add_credentials(self, job_template, credential, rando): job_template.admin_role.members.add(rando) credential.read_role.members.add(rando) # without permission to credential, user can not attach it assert not JobTemplateAccess(rando).can_attach( job_template, credential, 'credentials', {}) - def test_job_template_can_add_extra_credentials(self, job_template, credential, rando): + def test_job_template_can_add_credentials(self, job_template, credential, rando): job_template.admin_role.members.add(rando) credential.use_role.members.add(rando) # user has permission to apply credential diff --git a/awx/ui/client/src/job-submission/job-submission-factories/launchjob.factory.js b/awx/ui/client/src/job-submission/job-submission-factories/launchjob.factory.js index b12f417ba5..e8c6553241 100644 --- a/awx/ui/client/src/job-submission/job-submission-factories/launchjob.factory.js +++ b/awx/ui/client/src/job-submission/job-submission-factories/launchjob.factory.js @@ -123,9 +123,9 @@ export default if(!Empty(scope.selected_credentials.machine)) { job_launch_data.credential_id = scope.selected_credentials.machine.id; } - job_launch_data.extra_credentials = []; + job_launch_data.credentials = []; scope.selected_credentials.extra.forEach((extraCredential) => { - job_launch_data.extra_credentials.push(extraCredential.id); + job_launch_data.credentials.push(extraCredential.id); }); } diff --git a/awx/ui_next/src/components/PromptDetail/data.job_template.json b/awx/ui_next/src/components/PromptDetail/data.job_template.json index 0f29f134d2..4a3653f842 100644 --- a/awx/ui_next/src/components/PromptDetail/data.job_template.json +++ b/awx/ui_next/src/components/PromptDetail/data.job_template.json @@ -9,7 +9,6 @@ "labels": "/api/v2/job_templates/7/labels/", "inventory": "/api/v2/inventories/1/", "project": "/api/v2/projects/6/", - "extra_credentials": "/api/v2/job_templates/7/extra_credentials/", "credentials": "/api/v2/job_templates/7/credentials/", "last_job": "/api/v2/jobs/12/", "jobs": "/api/v2/job_templates/7/jobs/", @@ -143,7 +142,6 @@ "type": "job" } ], - "extra_credentials": [], "credentials": [ { "id": 1, "kind": "ssh" , "name": "Credential 1" @@ -195,4 +193,4 @@ "job_slice_count": 1, "webhook_service": "github", "webhook_credential": 8 -} \ No newline at end of file +} diff --git a/awx/ui_next/src/screens/Job/shared/data.job.json b/awx/ui_next/src/screens/Job/shared/data.job.json index cc6d37b750..8bebbbda67 100644 --- a/awx/ui_next/src/screens/Job/shared/data.job.json +++ b/awx/ui_next/src/screens/Job/shared/data.job.json @@ -7,7 +7,6 @@ "labels": "/api/v2/jobs/2/labels/", "inventory": "/api/v2/inventories/1/", "project": "/api/v2/projects/6/", - "extra_credentials": "/api/v2/jobs/2/extra_credentials/", "credentials": "/api/v2/jobs/2/credentials/", "unified_job_template": "/api/v2/job_templates/7/", "stdout": "/api/v2/jobs/2/stdout/", @@ -80,7 +79,6 @@ "count": 0, "results": [] }, - "extra_credentials": [], "credentials": [ { "id": 1, diff --git a/awx/ui_next/src/screens/Template/shared/data.job_template.json b/awx/ui_next/src/screens/Template/shared/data.job_template.json index 6f1caa3e3f..4d0cdb6aae 100644 --- a/awx/ui_next/src/screens/Template/shared/data.job_template.json +++ b/awx/ui_next/src/screens/Template/shared/data.job_template.json @@ -9,7 +9,6 @@ "labels": "/api/v2/job_templates/7/labels/", "inventory": "/api/v2/inventories/1/", "project": "/api/v2/projects/6/", - "extra_credentials": "/api/v2/job_templates/7/extra_credentials/", "credentials": "/api/v2/job_templates/7/credentials/", "last_job": "/api/v2/jobs/12/", "jobs": "/api/v2/job_templates/7/jobs/", @@ -118,7 +117,6 @@ "finished": "2019-10-01T14:34:35.142483Z", "type": "job" }], - "extra_credentials": [], "credentials": [{ "id": 1, "kind": "ssh", diff --git a/awxkit/awxkit/api/pages/credentials.py b/awxkit/awxkit/api/pages/credentials.py index 2ef8a7c05c..8a5e7e0eca 100644 --- a/awxkit/awxkit/api/pages/credentials.py +++ b/awxkit/awxkit/api/pages/credentials.py @@ -362,9 +362,7 @@ class Credentials(page.PageList, Credential): page.register_page([resources.credentials, - resources.related_credentials, - resources.job_extra_credentials, - resources.job_template_extra_credentials], + resources.related_credentials], Credentials) diff --git a/awxkit/awxkit/api/pages/job_templates.py b/awxkit/awxkit/api/pages/job_templates.py index 929383fd55..ad59bfb742 100644 --- a/awxkit/awxkit/api/pages/job_templates.py +++ b/awxkit/awxkit/api/pages/job_templates.py @@ -189,16 +189,6 @@ class JobTemplate( dict(id=kwargs['vault_credential'])) return ret - def add_extra_credential(self, credential): - with suppress(exc.NoContent): - self.related.extra_credentials.post( - dict(id=credential.id, associate=True)) - - def remove_extra_credential(self, credential): - with suppress(exc.NoContent): - self.related.extra_credentials.post( - dict(id=credential.id, disassociate=True)) - def add_credential(self, credential): with suppress(exc.NoContent): self.related.credentials.post( diff --git a/awxkit/awxkit/api/resources.py b/awxkit/awxkit/api/resources.py index 31b671df68..25995188f9 100644 --- a/awxkit/awxkit/api/resources.py +++ b/awxkit/awxkit/api/resources.py @@ -88,7 +88,6 @@ class Resources(object): _job_event = r'job_events/\d+/' _job_event_children = r'job_events/\d+/children/' _job_events = 'job_events/' - _job_extra_credentials = _job + 'extra_credentials/' _job_host_summaries = r'jobs/\d+/job_host_summaries/' _job_host_summary = r'job_host_summaries/\d+/' _job_job_event = r'jobs/\d+/job_events/\d+/' @@ -105,7 +104,6 @@ class Resources(object): _job_template_access_list = r'job_templates/\d+/access_list/' _job_template_callback = r'job_templates/\d+/callback/' _job_template_copy = r'job_templates/\d+/copy/' - _job_template_extra_credentials = _job_template + 'extra_credentials/' _job_template_jobs = r'job_templates/\d+/jobs/' _job_template_labels = r'job_templates/\d+/labels/' _job_template_launch = r'job_templates/\d+/launch/' diff --git a/docs/credentials/custom_credential_types.md b/docs/credentials/custom_credential_types.md index 238dad12ba..630db24b30 100644 --- a/docs/credentials/custom_credential_types.md +++ b/docs/credentials/custom_credential_types.md @@ -37,7 +37,7 @@ Important Changes two OpenStack credentials. * In the same manner as "promptable SSH credentials", when - ``ask_credential_on_launch = true``, ``JobTemplate.extra_credentials`` can be + ``ask_credential_on_launch = true``, ``JobTemplate.credentials`` can be specified in the launch payload. * Custom inventory sources can now utilize a ``Credential``; you @@ -221,9 +221,9 @@ API resources in `/api/v2/` now have two credential related fields: ... } -...and a new endpoint for fetching all "extra" credentials: +...and a new endpoint for fetching all credentials: - HTTP GET /api/v2/job_templates/N/extra_credentials/ + HTTP GET /api/v2/job_templates/N/credentials/ { 'count': N, @@ -239,21 +239,21 @@ Similar to other list attachment/detachment API views, cloud and network credentials can be created and attached via an `HTTP POST` at this new endpoint: - HTTP POST /api/v2/job_templates/N/extra_credentials/ + HTTP POST /api/v2/job_templates/N/credentials/ { 'id': , 'associate': True, } - HTTP POST /api/v2/job_templates/N/extra_credentials/ + HTTP POST /api/v2/job_templates/N/credentials/ { 'id': , 'disassociate': True, } - HTTP POST /api/v2/job_templates/N/extra_credentials/ + HTTP POST /api/v2/job_templates/N/credentials/ { 'name': 'My Credential', diff --git a/docs/prompting.md b/docs/prompting.md index c2f2f49b59..5f2d998022 100644 --- a/docs/prompting.md +++ b/docs/prompting.md @@ -283,7 +283,3 @@ of what happened. - Job template has machine & cloud credentials, set to prompt for credential on launch - Schedule for job template provides no credentials - Spawned job still uses all job template credentials - -**Credentials Deprecated Behavior** - - Manual launch providing `"extra_credentials": []` should launch with no job credentials - - Such jobs cannot have schedules created from them