mirror of
https://github.com/ansible/awx.git
synced 2026-05-10 19:07:36 -02:30
Changing label functions to account for new relationships
Removing unreferenced get_orphaned_labels Forcing forks and job_slice_count to be >=0
This commit is contained in:
committed by
Alan Rominger
parent
64dad61b29
commit
b501b30db4
@@ -3633,8 +3633,8 @@ class LaunchConfigurationBaseSerializer(BaseSerializer):
|
|||||||
skip_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
skip_tags = serializers.CharField(allow_blank=True, allow_null=True, required=False, default=None)
|
||||||
diff_mode = serializers.BooleanField(required=False, allow_null=True, default=None)
|
diff_mode = serializers.BooleanField(required=False, allow_null=True, default=None)
|
||||||
verbosity = serializers.ChoiceField(allow_null=True, required=False, default=None, choices=VERBOSITY_CHOICES)
|
verbosity = serializers.ChoiceField(allow_null=True, required=False, default=None, choices=VERBOSITY_CHOICES)
|
||||||
forks = serializers.IntegerField(required=False, allow_null=True, default=None)
|
forks = serializers.IntegerField(required=False, allow_null=True, min_value=0, default=None)
|
||||||
job_slice_count = serializers.IntegerField(required=False, allow_null=True, default=None)
|
job_slice_count = serializers.IntegerField(required=False, allow_null=True, min_value=0, default=None)
|
||||||
timeout = serializers.IntegerField(required=False, allow_null=True, default=None)
|
timeout = serializers.IntegerField(required=False, allow_null=True, default=None)
|
||||||
exclude_errors = ()
|
exclude_errors = ()
|
||||||
|
|
||||||
@@ -4141,8 +4141,8 @@ class JobLaunchSerializer(BaseSerializer):
|
|||||||
verbosity = serializers.ChoiceField(required=False, choices=VERBOSITY_CHOICES, write_only=True)
|
verbosity = serializers.ChoiceField(required=False, choices=VERBOSITY_CHOICES, write_only=True)
|
||||||
execution_environment = serializers.PrimaryKeyRelatedField(queryset=ExecutionEnvironment.objects.all(), required=False)
|
execution_environment = serializers.PrimaryKeyRelatedField(queryset=ExecutionEnvironment.objects.all(), required=False)
|
||||||
labels = serializers.PrimaryKeyRelatedField(many=True, queryset=Label.objects.all(), required=False)
|
labels = serializers.PrimaryKeyRelatedField(many=True, queryset=Label.objects.all(), required=False)
|
||||||
forks = serializers.IntegerField(required=False, write_only=True, default=1)
|
forks = serializers.IntegerField(required=False, write_only=True, min_value=0, default=1)
|
||||||
job_slice_count = serializers.IntegerField(required=False, write_only=True, default=0)
|
job_slice_count = serializers.IntegerField(required=False, write_only=True, min_value=0, default=0)
|
||||||
timeout = serializers.IntegerField(required=False, write_only=True, default=0)
|
timeout = serializers.IntegerField(required=False, write_only=True, default=0)
|
||||||
instance_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=InstanceGroup.objects.all(), required=False)
|
instance_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=InstanceGroup.objects.all(), required=False)
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ from awx.api.versioning import reverse
|
|||||||
from awx.main.models.base import CommonModelNameNotUnique
|
from awx.main.models.base import CommonModelNameNotUnique
|
||||||
from awx.main.models.unified_jobs import UnifiedJobTemplate, UnifiedJob
|
from awx.main.models.unified_jobs import UnifiedJobTemplate, UnifiedJob
|
||||||
from awx.main.models.inventory import Inventory
|
from awx.main.models.inventory import Inventory
|
||||||
|
from awx.main.models.schedules import Schedule
|
||||||
|
from awx.main.models.workflow import WorkflowJobTemplateNode, WorkflowJobNode
|
||||||
|
|
||||||
__all__ = ('Label',)
|
__all__ = ('Label',)
|
||||||
|
|
||||||
@@ -34,16 +36,22 @@ class Label(CommonModelNameNotUnique):
|
|||||||
def get_absolute_url(self, request=None):
|
def get_absolute_url(self, request=None):
|
||||||
return reverse('api:label_detail', kwargs={'pk': self.pk}, request=request)
|
return reverse('api:label_detail', kwargs={'pk': self.pk}, request=request)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_orphaned_labels():
|
|
||||||
return Label.objects.filter(organization=None, unifiedjobtemplate_labels__isnull=True, inventory_labels__isnull=True)
|
|
||||||
|
|
||||||
def is_detached(self):
|
def is_detached(self):
|
||||||
return Label.objects.filter(id=self.id, unifiedjob_labels__isnull=True, unifiedjobtemplate_labels__isnull=True, inventory_labels__isnull=True).exists()
|
return Label.objects.filter(
|
||||||
|
id=self.id,
|
||||||
|
unifiedjob_labels__isnull=True,
|
||||||
|
unifiedjobtemplate_labels__isnull=True,
|
||||||
|
inventory_labels__isnull=True,
|
||||||
|
schedule_labels__isnull=True,
|
||||||
|
workflowjobtemplatenode_labels__isnull=True,
|
||||||
|
workflowjobnode_labels=True,
|
||||||
|
).exists()
|
||||||
|
|
||||||
def is_candidate_for_detach(self):
|
def is_candidate_for_detach(self):
|
||||||
|
count = UnifiedJob.objects.filter(labels__in=[self.id]).count() # Both Jobs and WFJobs
|
||||||
c1 = UnifiedJob.objects.filter(labels__in=[self.id]).count()
|
count += UnifiedJobTemplate.objects.filter(labels__in=[self.id]).count() # Both JTs and WFJT
|
||||||
c2 = UnifiedJobTemplate.objects.filter(labels__in=[self.id]).count()
|
count += Inventory.objects.filter(labels__in=[self.id]).count()
|
||||||
c3 = Inventory.objects.filter(labels__in=[self.id]).count()
|
count += Schedule.objects.filter(labels__in=[self.id]).count()
|
||||||
return (c1 + c2 + c3 - 1) == 0
|
count += WorkflowJobTemplateNode.objects.filter(labels__in=[self.id]).count()
|
||||||
|
count += WorkflowJobNode.objects.filter(labels__in=[self.id]).count()
|
||||||
|
return (count - 1) == 0
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from awx.main.models.label import Label
|
from awx.main.models import (
|
||||||
from awx.main.models.unified_jobs import UnifiedJobTemplate, UnifiedJob
|
Label,
|
||||||
from awx.main.models.inventory import Inventory
|
UnifiedJobTemplate,
|
||||||
|
UnifiedJob,
|
||||||
|
Inventory,
|
||||||
|
Schedule,
|
||||||
|
WorkflowJobTemplateNode,
|
||||||
|
WorkflowJobNode,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
mock_query_set = mock.MagicMock()
|
mock_query_set = mock.MagicMock()
|
||||||
@@ -14,12 +20,6 @@ mock_objects = mock.MagicMock(filter=mock.MagicMock(return_value=mock_query_set)
|
|||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch('awx.main.models.label.Label.objects', mock_objects)
|
@mock.patch('awx.main.models.label.Label.objects', mock_objects)
|
||||||
class TestLabelFilterMocked:
|
class TestLabelFilterMocked:
|
||||||
def test_get_orphaned_labels(self, mocker):
|
|
||||||
ret = Label.get_orphaned_labels()
|
|
||||||
|
|
||||||
assert mock_query_set == ret
|
|
||||||
Label.objects.filter.assert_called_with(organization=None, unifiedjobtemplate_labels__isnull=True, inventory_labels__isnull=True)
|
|
||||||
|
|
||||||
def test_is_detached(self, mocker):
|
def test_is_detached(self, mocker):
|
||||||
mock_query_set.exists.return_value = True
|
mock_query_set.exists.return_value = True
|
||||||
|
|
||||||
@@ -27,7 +27,15 @@ class TestLabelFilterMocked:
|
|||||||
ret = label.is_detached()
|
ret = label.is_detached()
|
||||||
|
|
||||||
assert ret is True
|
assert ret is True
|
||||||
Label.objects.filter.assert_called_with(id=37, unifiedjob_labels__isnull=True, unifiedjobtemplate_labels__isnull=True, inventory_labels__isnull=True)
|
Label.objects.filter.assert_called_with(
|
||||||
|
id=37,
|
||||||
|
unifiedjob_labels__isnull=True,
|
||||||
|
unifiedjobtemplate_labels__isnull=True,
|
||||||
|
inventory_labels__isnull=True,
|
||||||
|
schedule_labels__isnull=True,
|
||||||
|
workflowjobtemplatenode_labels__isnull=True,
|
||||||
|
workflowjobnode_labels=True,
|
||||||
|
)
|
||||||
mock_query_set.exists.assert_called_with()
|
mock_query_set.exists.assert_called_with()
|
||||||
|
|
||||||
def test_is_detached_not(self, mocker):
|
def test_is_detached_not(self, mocker):
|
||||||
@@ -37,39 +45,102 @@ class TestLabelFilterMocked:
|
|||||||
ret = label.is_detached()
|
ret = label.is_detached()
|
||||||
|
|
||||||
assert ret is False
|
assert ret is False
|
||||||
Label.objects.filter.assert_called_with(id=37, unifiedjob_labels__isnull=True, unifiedjobtemplate_labels__isnull=True, inventory_labels__isnull=True)
|
Label.objects.filter.assert_called_with(
|
||||||
|
id=37,
|
||||||
|
unifiedjob_labels__isnull=True,
|
||||||
|
unifiedjobtemplate_labels__isnull=True,
|
||||||
|
inventory_labels__isnull=True,
|
||||||
|
schedule_labels__isnull=True,
|
||||||
|
workflowjobtemplatenode_labels__isnull=True,
|
||||||
|
workflowjobnode_labels=True,
|
||||||
|
)
|
||||||
|
|
||||||
mock_query_set.exists.assert_called_with()
|
mock_query_set.exists.assert_called_with()
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"jt_count,j_count,inv_count,expected",
|
"jt_count,j_count,inv_count,sched_count,wfnode_count,wfnodej_count,expected",
|
||||||
[
|
[
|
||||||
(1, 0, 0, True),
|
(1, 0, 0, 0, 0, 0, True),
|
||||||
(0, 1, 0, True),
|
(0, 1, 0, 0, 0, 0, True),
|
||||||
(0, 0, 1, True),
|
(1, 1, 0, 0, 0, 0, False),
|
||||||
(1, 1, 1, False),
|
(0, 0, 1, 0, 0, 0, True),
|
||||||
|
(1, 0, 1, 0, 0, 0, False),
|
||||||
|
(0, 1, 1, 0, 0, 0, False),
|
||||||
|
(1, 1, 1, 0, 0, 0, False),
|
||||||
|
(0, 0, 0, 1, 0, 0, True),
|
||||||
|
(1, 0, 0, 1, 0, 0, False),
|
||||||
|
(0, 1, 0, 1, 0, 0, False),
|
||||||
|
(1, 1, 0, 1, 0, 0, False),
|
||||||
|
(0, 0, 1, 1, 0, 0, False),
|
||||||
|
(1, 0, 1, 1, 0, 0, False),
|
||||||
|
(0, 1, 1, 1, 0, 0, False),
|
||||||
|
(1, 1, 1, 1, 0, 0, False),
|
||||||
|
(0, 0, 0, 0, 1, 0, True),
|
||||||
|
(1, 0, 0, 0, 1, 0, False),
|
||||||
|
(0, 1, 0, 0, 1, 0, False),
|
||||||
|
(1, 1, 0, 0, 1, 0, False),
|
||||||
|
(0, 0, 1, 0, 1, 0, False),
|
||||||
|
(1, 0, 1, 0, 1, 0, False),
|
||||||
|
(0, 1, 1, 0, 1, 0, False),
|
||||||
|
(1, 1, 1, 0, 1, 0, False),
|
||||||
|
(0, 0, 0, 1, 1, 0, False),
|
||||||
|
(1, 0, 0, 1, 1, 0, False),
|
||||||
|
(0, 1, 0, 1, 1, 0, False),
|
||||||
|
(1, 1, 0, 1, 1, 0, False),
|
||||||
|
(0, 0, 1, 1, 1, 0, False),
|
||||||
|
(1, 0, 1, 1, 1, 0, False),
|
||||||
|
(0, 1, 1, 1, 1, 0, False),
|
||||||
|
(1, 1, 1, 1, 1, 0, False),
|
||||||
|
(0, 0, 0, 0, 0, 1, True),
|
||||||
|
(1, 0, 0, 0, 0, 1, False),
|
||||||
|
(0, 1, 0, 0, 0, 1, False),
|
||||||
|
(1, 1, 0, 0, 0, 1, False),
|
||||||
|
(0, 0, 1, 0, 0, 1, False),
|
||||||
|
(1, 0, 1, 0, 0, 1, False),
|
||||||
|
(0, 1, 1, 0, 0, 1, False),
|
||||||
|
(1, 1, 1, 0, 0, 1, False),
|
||||||
|
(0, 0, 0, 1, 0, 1, False),
|
||||||
|
(1, 0, 0, 1, 0, 1, False),
|
||||||
|
(0, 1, 0, 1, 0, 1, False),
|
||||||
|
(1, 1, 0, 1, 0, 1, False),
|
||||||
|
(0, 0, 1, 1, 0, 1, False),
|
||||||
|
(1, 0, 1, 1, 0, 1, False),
|
||||||
|
(0, 1, 1, 1, 0, 1, False),
|
||||||
|
(1, 1, 1, 1, 0, 1, False),
|
||||||
|
(0, 0, 0, 0, 1, 1, False),
|
||||||
|
(1, 0, 0, 0, 1, 1, False),
|
||||||
|
(0, 1, 0, 0, 1, 1, False),
|
||||||
|
(1, 1, 0, 0, 1, 1, False),
|
||||||
|
(0, 0, 1, 0, 1, 1, False),
|
||||||
|
(1, 0, 1, 0, 1, 1, False),
|
||||||
|
(0, 1, 1, 0, 1, 1, False),
|
||||||
|
(1, 1, 1, 0, 1, 1, False),
|
||||||
|
(0, 0, 0, 1, 1, 1, False),
|
||||||
|
(1, 0, 0, 1, 1, 1, False),
|
||||||
|
(0, 1, 0, 1, 1, 1, False),
|
||||||
|
(1, 1, 0, 1, 1, 1, False),
|
||||||
|
(0, 0, 1, 1, 1, 1, False),
|
||||||
|
(1, 0, 1, 1, 1, 1, False),
|
||||||
|
(0, 1, 1, 1, 1, 1, False),
|
||||||
|
(1, 1, 1, 1, 1, 1, False),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_is_candidate_for_detach(self, mocker, jt_count, j_count, inv_count, expected):
|
def test_is_candidate_for_detach(self, mocker, jt_count, j_count, inv_count, sched_count, wfnode_count, wfnodej_count, expected):
|
||||||
mock_job_qs = mocker.MagicMock()
|
counts = [jt_count, j_count, inv_count, sched_count, wfnode_count, wfnodej_count]
|
||||||
mock_job_qs.count = mocker.MagicMock(return_value=j_count)
|
models = [UnifiedJobTemplate, UnifiedJob, Inventory, Schedule, WorkflowJobTemplateNode, WorkflowJobNode]
|
||||||
mocker.patch.object(UnifiedJob, 'objects', mocker.MagicMock(filter=mocker.MagicMock(return_value=mock_job_qs)))
|
mockers = []
|
||||||
|
for index in range(0, len(models)):
|
||||||
mock_jt_qs = mocker.MagicMock()
|
a_mocker = mocker.MagicMock()
|
||||||
mock_jt_qs.count = mocker.MagicMock(return_value=jt_count)
|
a_mocker.count = mocker.MagicMock(return_value=counts[index])
|
||||||
mocker.patch.object(UnifiedJobTemplate, 'objects', mocker.MagicMock(filter=mocker.MagicMock(return_value=mock_jt_qs)))
|
mocker.patch.object(models[index], 'objects', mocker.MagicMock(filter=mocker.MagicMock(return_value=a_mocker)))
|
||||||
|
mockers.append(a_mocker)
|
||||||
mock_inv_qs = mocker.MagicMock()
|
|
||||||
mock_inv_qs.count = mocker.MagicMock(return_value=inv_count)
|
|
||||||
mocker.patch.object(Inventory, 'objects', mocker.MagicMock(filter=mocker.MagicMock(return_value=mock_inv_qs)))
|
|
||||||
|
|
||||||
label = Label(id=37)
|
label = Label(id=37)
|
||||||
ret = label.is_candidate_for_detach()
|
ret = label.is_candidate_for_detach()
|
||||||
|
|
||||||
UnifiedJob.objects.filter.assert_called_with(labels__in=[label.id])
|
for index in range(0, len(models)):
|
||||||
UnifiedJobTemplate.objects.filter.assert_called_with(labels__in=[label.id])
|
models[index].objects.filter.assert_called_with(labels__in=[label.id])
|
||||||
Inventory.objects.filter.assert_called_with(labels__in=[label.id])
|
for index in range(0, len(mockers)):
|
||||||
mock_job_qs.count.assert_called_with()
|
mockers[index].count.assert_called_with()
|
||||||
mock_jt_qs.count.assert_called_with()
|
|
||||||
mock_inv_qs.count.assert_called_with()
|
|
||||||
|
|
||||||
assert ret is expected
|
assert ret is expected
|
||||||
|
|||||||
Reference in New Issue
Block a user