diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 374f9f9f22..11a5c0adaa 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -178,7 +178,7 @@ def apply_cluster_membership_policies(self): g.instances.append(i.obj.id) g.obj.instances.add(i.obj) i.groups.append(g.obj.id) - handle_ha_toplogy_changes.apply_async() + handle_ha_toplogy_changes() @shared_task(queue='tower_broadcast_all', bind=True, base=LogErrorsTask) diff --git a/awx/main/tests/functional/test_instances.py b/awx/main/tests/functional/test_instances.py index 3454371037..11484dfc6e 100644 --- a/awx/main/tests/functional/test_instances.py +++ b/awx/main/tests/functional/test_instances.py @@ -1,7 +1,8 @@ import pytest +import mock -from awx.main.models import AdHocCommand, InventoryUpdate, Job, JobTemplate, ProjectUpdate -from awx.main.models import Instance +from awx.main.models import AdHocCommand, InventoryUpdate, Job, JobTemplate, ProjectUpdate, Instance +from awx.main.tasks import apply_cluster_membership_policies from awx.api.versioning import reverse @@ -30,6 +31,130 @@ def test_instance_dup(org_admin, organization, project, instance_factory, instan assert api_num_instances_oa == (actual_num_instances - 1) +@pytest.mark.django_db +@mock.patch('awx.main.tasks.handle_ha_toplogy_changes', return_value=None) +def test_policy_instance_few_instances(mock, instance_factory, instance_group_factory): + i1 = instance_factory("i1") + ig_1 = instance_group_factory("ig1", percentage=25) + ig_2 = instance_group_factory("ig2", percentage=25) + ig_3 = instance_group_factory("ig3", percentage=25) + ig_4 = instance_group_factory("ig4", percentage=25) + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 1 + assert i1 in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i1 in ig_2.instances.all() + assert len(ig_3.instances.all()) == 1 + assert i1 in ig_3.instances.all() + assert len(ig_4.instances.all()) == 1 + assert i1 in ig_4.instances.all() + i2 = instance_factory("i2") + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 1 + assert i1 in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i2 in ig_2.instances.all() + assert len(ig_3.instances.all()) == 1 + assert i1 in ig_3.instances.all() + assert len(ig_4.instances.all()) == 1 + assert i2 in ig_4.instances.all() + + +@pytest.mark.django_db +@mock.patch('awx.main.tasks.handle_ha_toplogy_changes', return_value=None) +def test_policy_instance_distribution_uneven(mock, instance_factory, instance_group_factory): + i1 = instance_factory("i1") + i2 = instance_factory("i2") + i3 = instance_factory("i3") + ig_1 = instance_group_factory("ig1", percentage=25) + ig_2 = instance_group_factory("ig2", percentage=25) + ig_3 = instance_group_factory("ig3", percentage=25) + ig_4 = instance_group_factory("ig4", percentage=25) + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 1 + assert i1 in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i2 in ig_2.instances.all() + assert len(ig_3.instances.all()) == 1 + assert i3 in ig_3.instances.all() + assert len(ig_4.instances.all()) == 1 + assert i1 in ig_4.instances.all() + + +@pytest.mark.django_db +@mock.patch('awx.main.tasks.handle_ha_toplogy_changes', return_value=None) +def test_policy_instance_distribution_even(mock, instance_factory, instance_group_factory): + i1 = instance_factory("i1") + i2 = instance_factory("i2") + i3 = instance_factory("i3") + i4 = instance_factory("i4") + ig_1 = instance_group_factory("ig1", percentage=25) + ig_2 = instance_group_factory("ig2", percentage=25) + ig_3 = instance_group_factory("ig3", percentage=25) + ig_4 = instance_group_factory("ig4", percentage=25) + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 1 + assert i1 in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i2 in ig_2.instances.all() + assert len(ig_3.instances.all()) == 1 + assert i3 in ig_3.instances.all() + assert len(ig_4.instances.all()) == 1 + assert i4 in ig_4.instances.all() + ig_1.policy_instance_minimum = 2 + ig_1.save() + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 2 + assert i1 in ig_1.instances.all() + assert i2 in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i3 in ig_2.instances.all() + assert len(ig_3.instances.all()) == 1 + assert i4 in ig_3.instances.all() + assert len(ig_4.instances.all()) == 1 + assert i1 in ig_4.instances.all() + + +@pytest.mark.django_db +@mock.patch('awx.main.tasks.handle_ha_toplogy_changes', return_value=None) +def test_policy_instance_distribution_simultaneous(mock, instance_factory, instance_group_factory): + i1 = instance_factory("i1") + i2 = instance_factory("i2") + i3 = instance_factory("i3") + i4 = instance_factory("i4") + ig_1 = instance_group_factory("ig1", percentage=25, minimum=2) + ig_2 = instance_group_factory("ig2", percentage=25) + ig_3 = instance_group_factory("ig3", percentage=25) + ig_4 = instance_group_factory("ig4", percentage=25) + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 2 + assert i1 in ig_1.instances.all() + assert i2 in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i3 in ig_2.instances.all() + assert len(ig_3.instances.all()) == 1 + assert i4 in ig_3.instances.all() + assert len(ig_4.instances.all()) == 1 + assert i1 in ig_4.instances.all() + + +@pytest.mark.django_db +@mock.patch('awx.main.tasks.handle_ha_toplogy_changes', return_value=None) +def test_policy_instance_list_manually_managed(mock, instance_factory, instance_group_factory): + i1 = instance_factory("i1") + i2 = instance_factory("i2") + ig_1 = instance_group_factory("ig1", percentage=100, minimum=2) + ig_2 = instance_group_factory("ig2") + ig_2.policy_instance_list = [i2.hostname] + ig_2.save() + apply_cluster_membership_policies() + assert len(ig_1.instances.all()) == 1 + assert i1 in ig_1.instances.all() + assert i2 not in ig_1.instances.all() + assert len(ig_2.instances.all()) == 1 + assert i2 in ig_2.instances.all() + + @pytest.mark.django_db def test_basic_instance_group_membership(instance_group_factory, default_instance_group, job_factory): j = job_factory()