mirror of
https://github.com/ansible/awx.git
synced 2026-03-10 05:59:28 -02:30
Merge pull request #1282 from ryanpetrello/fix-1268
add exception handling to deprecated v1 credential support
This commit is contained in:
@@ -3,12 +3,14 @@
|
|||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.conf import fields
|
from awx.conf import fields
|
||||||
|
from awx.main.models import Credential
|
||||||
|
|
||||||
__all__ = ['BooleanNullField', 'CharNullField', 'ChoiceNullField', 'VerbatimField']
|
__all__ = ['BooleanNullField', 'CharNullField', 'ChoiceNullField', 'VerbatimField']
|
||||||
|
|
||||||
@@ -87,3 +89,20 @@ class OAuth2ProviderField(fields.DictField):
|
|||||||
if invalid_flags:
|
if invalid_flags:
|
||||||
self.fail('invalid_key_names', invalid_key_names=', '.join(list(invalid_flags)))
|
self.fail('invalid_key_names', invalid_key_names=', '.join(list(invalid_flags)))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class DeprecatedCredentialField(serializers.IntegerField):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
kwargs['allow_null'] = True
|
||||||
|
kwargs['default'] = None
|
||||||
|
kwargs['min_value'] = 1
|
||||||
|
kwargs['help_text'] = 'This resource has been deprecated and will be removed in a future release'
|
||||||
|
super(DeprecatedCredentialField, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def to_internal_value(self, pk):
|
||||||
|
try:
|
||||||
|
Credential.objects.get(pk=pk)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
raise serializers.ValidationError(_('Credential {} does not exist').format(pk))
|
||||||
|
return pk
|
||||||
|
|||||||
@@ -56,12 +56,11 @@ from awx.main.validators import vars_validate_or_raise
|
|||||||
|
|
||||||
from awx.conf.license import feature_enabled
|
from awx.conf.license import feature_enabled
|
||||||
from awx.api.versioning import reverse, get_request_version
|
from awx.api.versioning import reverse, get_request_version
|
||||||
from awx.api.fields import BooleanNullField, CharNullField, ChoiceNullField, VerbatimField
|
from awx.api.fields import (BooleanNullField, CharNullField, ChoiceNullField,
|
||||||
|
VerbatimField, DeprecatedCredentialField)
|
||||||
|
|
||||||
logger = logging.getLogger('awx.api.serializers')
|
logger = logging.getLogger('awx.api.serializers')
|
||||||
|
|
||||||
DEPRECATED = 'This resource has been deprecated and will be removed in a future release'
|
|
||||||
|
|
||||||
# Fields that should be summarized regardless of object type.
|
# Fields that should be summarized regardless of object type.
|
||||||
DEFAULT_SUMMARY_FIELDS = ('id', 'name', 'description')# , 'created_by', 'modified_by')#, 'type')
|
DEFAULT_SUMMARY_FIELDS = ('id', 'name', 'description')# , 'created_by', 'modified_by')#, 'type')
|
||||||
|
|
||||||
@@ -1957,9 +1956,7 @@ class CustomInventoryScriptSerializer(BaseSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class InventorySourceOptionsSerializer(BaseSerializer):
|
class InventorySourceOptionsSerializer(BaseSerializer):
|
||||||
credential = models.PositiveIntegerField(
|
credential = DeprecatedCredentialField()
|
||||||
blank=True, null=True, default=None,
|
|
||||||
help_text='This resource has been deprecated and will be removed in a future release')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ('*', 'source', 'source_path', 'source_script', 'source_vars', 'credential',
|
fields = ('*', 'source', 'source_path', 'source_script', 'source_vars', 'credential',
|
||||||
@@ -2818,15 +2815,11 @@ class V1JobOptionsSerializer(BaseSerializer):
|
|||||||
model = Credential
|
model = Credential
|
||||||
fields = ('*', 'cloud_credential', 'network_credential')
|
fields = ('*', 'cloud_credential', 'network_credential')
|
||||||
|
|
||||||
V1_FIELDS = {
|
V1_FIELDS = ('cloud_credential', 'network_credential',)
|
||||||
'cloud_credential': models.PositiveIntegerField(blank=True, null=True, default=None, help_text=DEPRECATED),
|
|
||||||
'network_credential': models.PositiveIntegerField(blank=True, null=True, default=None, help_text=DEPRECATED),
|
|
||||||
}
|
|
||||||
|
|
||||||
def build_field(self, field_name, info, model_class, nested_depth):
|
def build_field(self, field_name, info, model_class, nested_depth):
|
||||||
if field_name in self.V1_FIELDS:
|
if field_name in self.V1_FIELDS:
|
||||||
return self.build_standard_field(field_name,
|
return (DeprecatedCredentialField, {})
|
||||||
self.V1_FIELDS[field_name])
|
|
||||||
return super(V1JobOptionsSerializer, self).build_field(field_name, info, model_class, nested_depth)
|
return super(V1JobOptionsSerializer, self).build_field(field_name, info, model_class, nested_depth)
|
||||||
|
|
||||||
|
|
||||||
@@ -2837,15 +2830,11 @@ class LegacyCredentialFields(BaseSerializer):
|
|||||||
model = Credential
|
model = Credential
|
||||||
fields = ('*', 'credential', 'vault_credential')
|
fields = ('*', 'credential', 'vault_credential')
|
||||||
|
|
||||||
LEGACY_FIELDS = {
|
LEGACY_FIELDS = ('credential', 'vault_credential',)
|
||||||
'credential': models.PositiveIntegerField(blank=True, null=True, default=None, help_text=DEPRECATED),
|
|
||||||
'vault_credential': models.PositiveIntegerField(blank=True, null=True, default=None, help_text=DEPRECATED),
|
|
||||||
}
|
|
||||||
|
|
||||||
def build_field(self, field_name, info, model_class, nested_depth):
|
def build_field(self, field_name, info, model_class, nested_depth):
|
||||||
if field_name in self.LEGACY_FIELDS:
|
if field_name in self.LEGACY_FIELDS:
|
||||||
return self.build_standard_field(field_name,
|
return (DeprecatedCredentialField, {})
|
||||||
self.LEGACY_FIELDS[field_name])
|
|
||||||
return super(LegacyCredentialFields, self).build_field(field_name, info, model_class, nested_depth)
|
return super(LegacyCredentialFields, self).build_field(field_name, info, model_class, nested_depth)
|
||||||
|
|
||||||
|
|
||||||
@@ -3718,9 +3707,7 @@ class LaunchConfigurationBaseSerializer(BaseSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class WorkflowJobTemplateNodeSerializer(LaunchConfigurationBaseSerializer):
|
class WorkflowJobTemplateNodeSerializer(LaunchConfigurationBaseSerializer):
|
||||||
credential = models.PositiveIntegerField(
|
credential = DeprecatedCredentialField()
|
||||||
blank=True, null=True, default=None,
|
|
||||||
help_text='This resource has been deprecated and will be removed in a future release')
|
|
||||||
success_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
success_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
||||||
failure_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
failure_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
||||||
always_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
always_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
||||||
@@ -3811,9 +3798,7 @@ class WorkflowJobTemplateNodeSerializer(LaunchConfigurationBaseSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class WorkflowJobNodeSerializer(LaunchConfigurationBaseSerializer):
|
class WorkflowJobNodeSerializer(LaunchConfigurationBaseSerializer):
|
||||||
credential = models.PositiveIntegerField(
|
credential = DeprecatedCredentialField()
|
||||||
blank=True, null=True, default=None,
|
|
||||||
help_text='This resource has been deprecated and will be removed in a future release')
|
|
||||||
success_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
success_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
||||||
failure_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
failure_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
||||||
always_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
always_nodes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
import mock
|
import mock
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -5,6 +6,14 @@ from awx.main.models import Credential, Job
|
|||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ec2_source(inventory, project):
|
||||||
|
with mock.patch('awx.main.models.unified_jobs.UnifiedJobTemplate.update'):
|
||||||
|
return inventory.inventory_sources.create(
|
||||||
|
name='some_source', update_on_project_update=True, source='ec2',
|
||||||
|
source_project=project, scm_last_revision=project.scm_revision)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def job_template(job_template, project, inventory):
|
def job_template(job_template, project, inventory):
|
||||||
job_template.playbook = 'helloworld.yml'
|
job_template.playbook = 'helloworld.yml'
|
||||||
@@ -34,6 +43,14 @@ def test_ssh_credential_access(get, job_template, admin, machine_credential):
|
|||||||
assert resp.data['summary_fields']['credential']['kind'] == 'ssh'
|
assert resp.data['summary_fields']['credential']['kind'] == 'ssh'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@pytest.mark.parametrize('key', ('credential', 'vault_credential', 'cloud_credential', 'network_credential'))
|
||||||
|
def test_invalid_credential_update(get, patch, job_template, admin, key):
|
||||||
|
url = reverse('api:job_template_detail', kwargs={'pk': job_template.pk, 'version': 'v1'})
|
||||||
|
resp = patch(url, {key: 999999}, admin, expect=400)
|
||||||
|
assert 'Credential 999999 does not exist' in json.loads(resp.content)[key]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_ssh_credential_update(get, patch, job_template, admin, machine_credential):
|
def test_ssh_credential_update(get, patch, job_template, admin, machine_credential):
|
||||||
url = reverse('api:job_template_detail', kwargs={'pk': job_template.pk})
|
url = reverse('api:job_template_detail', kwargs={'pk': job_template.pk})
|
||||||
@@ -362,3 +379,18 @@ def test_rbac_default_credential_usage(get, post, job_template, alice, machine_c
|
|||||||
new_cred.use_role.members.add(alice)
|
new_cred.use_role.members.add(alice)
|
||||||
url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk})
|
url = reverse('api:job_template_launch', kwargs={'pk': job_template.pk})
|
||||||
post(url, {'credential': new_cred.pk}, alice, expect=201)
|
post(url, {'credential': new_cred.pk}, alice, expect=201)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_inventory_source_deprecated_credential(get, patch, admin, ec2_source, credential):
|
||||||
|
url = reverse('api:inventory_source_detail', kwargs={'pk': ec2_source.pk})
|
||||||
|
patch(url, {'credential': credential.pk}, admin, expect=200)
|
||||||
|
resp = get(url, admin, expect=200)
|
||||||
|
assert json.loads(resp.content)['credential'] == credential.pk
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_inventory_source_invalid_deprecated_credential(patch, admin, ec2_source, credential):
|
||||||
|
url = reverse('api:inventory_source_detail', kwargs={'pk': ec2_source.pk})
|
||||||
|
resp = patch(url, {'credential': 999999}, admin, expect=400)
|
||||||
|
assert 'Credential 999999 does not exist' in resp.content
|
||||||
|
|||||||
Reference in New Issue
Block a user