diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index fec83b854e..3d158315d3 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1427,7 +1427,7 @@ class CredentialInputSourceDetail(RetrieveUpdateDestroyAPIView): serializer_class = serializers.CredentialInputSourceSerializer -class CredentialInputSourceList(ListCreateAPIView): +class CredentialInputSourceList(ListAPIView): view_name = _("Credential Input Sources") @@ -1435,7 +1435,7 @@ class CredentialInputSourceList(ListCreateAPIView): serializer_class = serializers.CredentialInputSourceSerializer -class CredentialInputSourceSubList(SubListAPIView): +class CredentialInputSourceSubList(SubListCreateAttachDetachAPIView): view_name = _("Credential Input Sources") diff --git a/awx/api/views/root.py b/awx/api/views/root.py index 66bc11b710..c7ecbbeef5 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -101,7 +101,6 @@ class ApiVersionRootView(APIView): data['credentials'] = reverse('api:credential_list', request=request) if get_request_version(request) > 1: data['credential_types'] = reverse('api:credential_type_list', request=request) - data['credential_input_sources'] = reverse('api:credential_input_source_list', request=request) data['applications'] = reverse('api:o_auth2_application_list', request=request) data['tokens'] = reverse('api:o_auth2_token_list', request=request) data['inventory'] = reverse('api:inventory_list', request=request) diff --git a/awx/main/tests/functional/api/test_credential_input_sources.py b/awx/main/tests/functional/api/test_credential_input_sources.py index 3524ca70fe..4f0cb371a6 100644 --- a/awx/main/tests/functional/api/test_credential_input_sources.py +++ b/awx/main/tests/functional/api/test_credential_input_sources.py @@ -1,115 +1,126 @@ import pytest +from awx.main.models import CredentialInputSource from awx.api.versioning import reverse @pytest.mark.django_db -def test_create_credential_input_source(get, post, admin, vault_credential, external_credential): - list_url = reverse( - 'api:credential_input_source_list', - kwargs={'version': 'v2'} - ) +def test_associate_credential_input_source(get, post, admin, vault_credential, external_credential): sublist_url = reverse( 'api:credential_input_source_sublist', kwargs={'version': 'v2', 'pk': vault_credential.pk} ) + + # attach params = { 'source_credential': external_credential.pk, - 'target_credential': vault_credential.pk, - 'input_field_name': 'vault_password' + 'input_field_name': 'vault_password', + 'associate': True } - response = post(list_url, params, admin) + response = post(sublist_url, params, admin) assert response.status_code == 201 - response = get(response.data['url'], admin) - assert response.status_code == 200 - - response = get(list_url, admin) - assert response.status_code == 200 - assert response.data['count'] == 1 + detail = get(response.data['url'], admin) + assert detail.status_code == 200 response = get(sublist_url, admin) assert response.status_code == 200 assert response.data['count'] == 1 + assert get(reverse( + 'api:credential_input_source_list', + kwargs={'version': 'v2'} + ), admin).data['count'] == 1 + assert CredentialInputSource.objects.count() == 1 + + # detach + params = { + 'id': detail.data['id'], + 'disassociate': True + } + response = post(sublist_url, params, admin) + assert response.status_code == 204 + + response = get(sublist_url, admin) + assert response.status_code == 200 + assert response.data['count'] == 0 + assert get(reverse( + 'api:credential_input_source_list', + kwargs={'version': 'v2'} + ), admin).data['count'] == 0 + assert CredentialInputSource.objects.count() == 0 @pytest.mark.django_db -def test_create_credential_input_source_using_sublist_returns_405(post, admin, vault_credential, external_credential): - sublist_url = reverse( - 'api:credential_input_source_sublist', - kwargs={'version': 'v2', 'pk': vault_credential.pk} - ) +def test_cannot_create_from_list(get, post, admin, vault_credential, external_credential): params = { 'source_credential': external_credential.pk, 'target_credential': vault_credential.pk, - 'input_field_name': 'vault_password' + 'input_field_name': 'vault_password', } - response = post(sublist_url, params, admin) - assert response.status_code == 405 + assert post(reverse( + 'api:credential_input_source_list', + kwargs={'version': 'v2'} + ), params, admin).status_code == 405 @pytest.mark.django_db def test_create_credential_input_source_with_external_target_returns_400(post, admin, external_credential, other_external_credential): - list_url = reverse( - 'api:credential_input_source_list', - kwargs={'version': 'v2'} + sublist_url = reverse( + 'api:credential_input_source_sublist', + kwargs={'version': 'v2', 'pk': other_external_credential.pk} ) params = { 'source_credential': external_credential.pk, - 'target_credential': other_external_credential.pk, - 'input_field_name': 'token' + 'input_field_name': 'token', + 'associate': True, } - response = post(list_url, params, admin) + response = post(sublist_url, params, admin) assert response.status_code == 400 assert response.data['target_credential'] == ['Target must be a non-external credential'] @pytest.mark.django_db def test_create_credential_input_source_with_non_external_source_returns_400(post, admin, credential, vault_credential): - list_url = reverse( - 'api:credential_input_source_list', - kwargs={'version': 'v2'} + sublist_url = reverse( + 'api:credential_input_source_sublist', + kwargs={'version': 'v2', 'pk': vault_credential.pk} ) params = { 'source_credential': credential.pk, - 'target_credential': vault_credential.pk, 'input_field_name': 'vault_password' } - response = post(list_url, params, admin) + response = post(sublist_url, params, admin) assert response.status_code == 400 assert response.data['source_credential'] == ['Source must be an external credential'] @pytest.mark.django_db def test_create_credential_input_source_with_undefined_input_returns_400(post, admin, vault_credential, external_credential): - list_url = reverse( - 'api:credential_input_source_list', - kwargs={'version': 'v2'} + sublist_url = reverse( + 'api:credential_input_source_sublist', + kwargs={'version': 'v2', 'pk': vault_credential.pk} ) params = { 'source_credential': external_credential.pk, - 'target_credential': vault_credential.pk, 'input_field_name': 'not_defined_for_credential_type' } - response = post(list_url, params, admin) + response = post(sublist_url, params, admin) assert response.status_code == 400 assert response.data['input_field_name'] == ['Input field must be defined on target credential.'] @pytest.mark.django_db def test_create_credential_input_source_with_already_used_input_returns_400(post, admin, vault_credential, external_credential, other_external_credential): - list_url = reverse( - 'api:credential_input_source_list', - kwargs={'version': 'v2'} + sublist_url = reverse( + 'api:credential_input_source_sublist', + kwargs={'version': 'v2', 'pk': vault_credential.pk} ) all_params = [{ 'source_credential': external_credential.pk, - 'target_credential': vault_credential.pk, 'input_field_name': 'vault_password' }, { 'source_credential': other_external_credential.pk, - 'target_credential': vault_credential.pk, 'input_field_name': 'vault_password' }] - all_responses = [post(list_url, params, admin) for params in all_params] + all_responses = [post(sublist_url, params, admin) for params in all_params] assert all_responses.pop().status_code == 400