From c8f4320b5820c43770fb4ab2671965aad54344c4 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Wed, 20 Sep 2017 14:27:14 -0400 Subject: [PATCH] allow the credential type to be changed for unused credentials see: https://github.com/ansible/ansible-tower/issues/7607 --- awx/api/serializers.py | 20 +++++-- .../tests/functional/api/test_credential.py | 52 ++++++++++++++----- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index a95a7f0c41..e6b1058778 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -2162,10 +2162,22 @@ class CredentialSerializer(BaseSerializer): def validate_credential_type(self, credential_type): if self.instance and credential_type.pk != self.instance.credential_type.pk: - raise ValidationError( - _('You cannot change the credential type of the credential, as it may break the functionality' - ' of the resources using it.'), - ) + for rel in ( + 'ad_hoc_commands', + 'insights_inventories', + 'inventorysources', + 'inventoryupdates', + 'jobs', + 'jobtemplates', + 'projects', + 'projectupdates', + 'workflowjobnodes' + ): + if getattr(self.instance, rel).count() > 0: + raise ValidationError( + _('You cannot change the credential type of the credential, as it may break the functionality' + ' of the resources using it.'), + ) return credential_type diff --git a/awx/main/tests/functional/api/test_credential.py b/awx/main/tests/functional/api/test_credential.py index feebfc08f4..b60d215e14 100644 --- a/awx/main/tests/functional/api/test_credential.py +++ b/awx/main/tests/functional/api/test_credential.py @@ -4,7 +4,9 @@ import re import mock # noqa import pytest -from awx.main.models.credential import Credential, CredentialType +from awx.main.models import (AdHocCommand, Credential, CredentialType, Job, JobTemplate, + Inventory, InventorySource, Project, + WorkflowJobNode) from awx.main.utils import decrypt_field from awx.api.versioning import reverse @@ -1410,7 +1412,17 @@ def test_field_removal(put, organization, admin, credentialtype_ssh, version, pa @pytest.mark.django_db -def test_credential_type_immutable_in_v2(patch, organization, admin, credentialtype_ssh, credentialtype_aws): +@pytest.mark.parametrize('relation, related_obj', [ + ['ad_hoc_commands', AdHocCommand()], + ['insights_inventories', Inventory()], + ['inventorysources', InventorySource()], + ['jobs', Job()], + ['jobtemplates', JobTemplate()], + ['projects', Project()], + ['workflowjobnodes', WorkflowJobNode()], +]) +def test_credential_type_mutability(patch, organization, admin, credentialtype_ssh, + credentialtype_aws, relation, related_obj): cred = Credential( credential_type=credentialtype_ssh, name='Best credential ever', @@ -1422,19 +1434,31 @@ def test_credential_type_immutable_in_v2(patch, organization, admin, credentialt ) cred.save() - response = patch( - reverse('api:credential_detail', kwargs={'version': 'v2', 'pk': cred.pk}), - { - 'credential_type': credentialtype_aws.pk, - 'inputs': { - 'username': u'jim', - 'password': u'pass' - } - }, - admin - ) + related_obj.save() + getattr(cred, relation).add(related_obj) + + def _change_credential_type(): + return patch( + reverse('api:credential_detail', kwargs={'version': 'v2', 'pk': cred.pk}), + { + 'credential_type': credentialtype_aws.pk, + 'inputs': { + 'username': u'jim', + 'password': u'pass' + } + }, + admin + ) + + response = _change_credential_type() assert response.status_code == 400 - assert 'credential_type' in response.data + expected = ['You cannot change the credential type of the credential, ' + 'as it may break the functionality of the resources using it.'] + assert response.data['credential_type'] == expected + + related_obj.delete() + response = _change_credential_type() + assert response.status_code == 200 @pytest.mark.django_db