mirror of
https://github.com/ansible/awx.git
synced 2026-03-05 10:41:05 -03:30
Always use controlplane as project update backup IG (#10949)
* Always use controlplane as project update backup IG Before, this was done conditionally to container_group jobs this logic changes it so that controlgroup will always be a firm backstop for project updates * Code a little more defensively to make unit tests pass * Fix unit tests
This commit is contained in:
@@ -615,16 +615,22 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def preferred_instance_groups(self):
|
def preferred_instance_groups(self):
|
||||||
|
'''
|
||||||
|
Project updates should pretty much always run on the control plane
|
||||||
|
however, we are not yet saying no to custom groupings within the control plane
|
||||||
|
Thus, we return custom groups and then unconditionally add the control plane
|
||||||
|
'''
|
||||||
if self.organization is not None:
|
if self.organization is not None:
|
||||||
organization_groups = [x for x in self.organization.instance_groups.all()]
|
organization_groups = [x for x in self.organization.instance_groups.all()]
|
||||||
else:
|
else:
|
||||||
organization_groups = []
|
organization_groups = []
|
||||||
template_groups = [x for x in super(ProjectUpdate, self).preferred_instance_groups]
|
template_groups = [x for x in super(ProjectUpdate, self).preferred_instance_groups]
|
||||||
selected_groups = template_groups + organization_groups
|
selected_groups = template_groups + organization_groups
|
||||||
if not any([not group.is_container_group for group in selected_groups]):
|
|
||||||
selected_groups = selected_groups + list(self.control_plane_instance_group)
|
controlplane_ig = self.control_plane_instance_group
|
||||||
if not selected_groups:
|
if controlplane_ig and controlplane_ig[0] and controlplane_ig[0] not in selected_groups:
|
||||||
return self.global_instance_groups
|
selected_groups += controlplane_ig
|
||||||
|
|
||||||
return selected_groups
|
return selected_groups
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
|
|||||||
@@ -84,6 +84,11 @@ def default_instance_group(instance_factory, instance_group_factory):
|
|||||||
return create_instance_group("default", instances=[create_instance("hostA")])
|
return create_instance_group("default", instances=[create_instance("hostA")])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def controlplane_instance_group(instance_factory, instance_group_factory):
|
||||||
|
return create_instance_group("controlplane", instances=[create_instance("hostA")])
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def job_template_with_survey_passwords_factory(job_template_factory):
|
def job_template_with_survey_passwords_factory(job_template_factory):
|
||||||
def rf(persisted):
|
def rf(persisted):
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ def test_multi_group_basic_job_launch(instance_factory, default_instance_group,
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_multi_group_with_shared_dependency(instance_factory, default_instance_group, mocker, instance_group_factory, job_template_factory):
|
def test_multi_group_with_shared_dependency(instance_factory, controlplane_instance_group, mocker, instance_group_factory, job_template_factory):
|
||||||
i1 = instance_factory("i1")
|
i1 = instance_factory("i1")
|
||||||
i2 = instance_factory("i2")
|
i2 = instance_factory("i2")
|
||||||
ig1 = instance_group_factory("ig1", instances=[i1])
|
ig1 = instance_group_factory("ig1", instances=[i1])
|
||||||
@@ -54,7 +54,7 @@ def test_multi_group_with_shared_dependency(instance_factory, default_instance_g
|
|||||||
with mocker.patch("awx.main.scheduler.TaskManager.start_task"):
|
with mocker.patch("awx.main.scheduler.TaskManager.start_task"):
|
||||||
TaskManager().schedule()
|
TaskManager().schedule()
|
||||||
pu = p.project_updates.first()
|
pu = p.project_updates.first()
|
||||||
TaskManager.start_task.assert_called_once_with(pu, default_instance_group, [j1, j2], default_instance_group.instances.all()[0])
|
TaskManager.start_task.assert_called_once_with(pu, controlplane_instance_group, [j1, j2], controlplane_instance_group.instances.all()[0])
|
||||||
pu.finished = pu.created + timedelta(seconds=1)
|
pu.finished = pu.created + timedelta(seconds=1)
|
||||||
pu.status = "successful"
|
pu.status = "successful"
|
||||||
pu.save()
|
pu.save()
|
||||||
|
|||||||
@@ -212,9 +212,9 @@ def test_multi_jt_capacity_blocking(default_instance_group, job_template_factory
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_single_job_dependencies_project_launch(default_instance_group, job_template_factory, mocker):
|
def test_single_job_dependencies_project_launch(controlplane_instance_group, job_template_factory, mocker):
|
||||||
objects = job_template_factory('jt', organization='org1', project='proj', inventory='inv', credential='cred', jobs=["job_should_start"])
|
objects = job_template_factory('jt', organization='org1', project='proj', inventory='inv', credential='cred', jobs=["job_should_start"])
|
||||||
instance = default_instance_group.instances.all()[0]
|
instance = controlplane_instance_group.instances.all()[0]
|
||||||
j = objects.jobs["job_should_start"]
|
j = objects.jobs["job_should_start"]
|
||||||
j.status = 'pending'
|
j.status = 'pending'
|
||||||
j.save()
|
j.save()
|
||||||
@@ -231,12 +231,12 @@ def test_single_job_dependencies_project_launch(default_instance_group, job_temp
|
|||||||
mock_pu.assert_called_once_with(j)
|
mock_pu.assert_called_once_with(j)
|
||||||
pu = [x for x in p.project_updates.all()]
|
pu = [x for x in p.project_updates.all()]
|
||||||
assert len(pu) == 1
|
assert len(pu) == 1
|
||||||
TaskManager.start_task.assert_called_once_with(pu[0], default_instance_group, [j], instance)
|
TaskManager.start_task.assert_called_once_with(pu[0], controlplane_instance_group, [j], instance)
|
||||||
pu[0].status = "successful"
|
pu[0].status = "successful"
|
||||||
pu[0].save()
|
pu[0].save()
|
||||||
with mock.patch("awx.main.scheduler.TaskManager.start_task"):
|
with mock.patch("awx.main.scheduler.TaskManager.start_task"):
|
||||||
TaskManager().schedule()
|
TaskManager().schedule()
|
||||||
TaskManager.start_task.assert_called_once_with(j, default_instance_group, [], instance)
|
TaskManager.start_task.assert_called_once_with(j, controlplane_instance_group, [], instance)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@@ -297,8 +297,8 @@ def test_job_dependency_with_already_updated(default_instance_group, job_templat
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_shared_dependencies_launch(default_instance_group, job_template_factory, mocker, inventory_source_factory):
|
def test_shared_dependencies_launch(controlplane_instance_group, job_template_factory, mocker, inventory_source_factory):
|
||||||
instance = default_instance_group.instances.all()[0]
|
instance = controlplane_instance_group.instances.all()[0]
|
||||||
objects = job_template_factory('jt', organization='org1', project='proj', inventory='inv', credential='cred', jobs=["first_job", "second_job"])
|
objects = job_template_factory('jt', organization='org1', project='proj', inventory='inv', credential='cred', jobs=["first_job", "second_job"])
|
||||||
j1 = objects.jobs["first_job"]
|
j1 = objects.jobs["first_job"]
|
||||||
j1.status = 'pending'
|
j1.status = 'pending'
|
||||||
@@ -326,7 +326,7 @@ def test_shared_dependencies_launch(default_instance_group, job_template_factory
|
|||||||
pu = p.project_updates.first()
|
pu = p.project_updates.first()
|
||||||
iu = ii.inventory_updates.first()
|
iu = ii.inventory_updates.first()
|
||||||
TaskManager.start_task.assert_has_calls(
|
TaskManager.start_task.assert_has_calls(
|
||||||
[mock.call(iu, default_instance_group, [j1, j2, pu], instance), mock.call(pu, default_instance_group, [j1, j2, iu], instance)]
|
[mock.call(iu, controlplane_instance_group, [j1, j2, pu], instance), mock.call(pu, controlplane_instance_group, [j1, j2, iu], instance)]
|
||||||
)
|
)
|
||||||
pu.status = "successful"
|
pu.status = "successful"
|
||||||
pu.finished = pu.created + timedelta(seconds=1)
|
pu.finished = pu.created + timedelta(seconds=1)
|
||||||
@@ -336,12 +336,12 @@ def test_shared_dependencies_launch(default_instance_group, job_template_factory
|
|||||||
iu.save()
|
iu.save()
|
||||||
with mock.patch("awx.main.scheduler.TaskManager.start_task"):
|
with mock.patch("awx.main.scheduler.TaskManager.start_task"):
|
||||||
TaskManager().schedule()
|
TaskManager().schedule()
|
||||||
TaskManager.start_task.assert_called_once_with(j1, default_instance_group, [], instance)
|
TaskManager.start_task.assert_called_once_with(j1, controlplane_instance_group, [], instance)
|
||||||
j1.status = "successful"
|
j1.status = "successful"
|
||||||
j1.save()
|
j1.save()
|
||||||
with mock.patch("awx.main.scheduler.TaskManager.start_task"):
|
with mock.patch("awx.main.scheduler.TaskManager.start_task"):
|
||||||
TaskManager().schedule()
|
TaskManager().schedule()
|
||||||
TaskManager.start_task.assert_called_once_with(j2, default_instance_group, [], instance)
|
TaskManager.start_task.assert_called_once_with(j2, controlplane_instance_group, [], instance)
|
||||||
pu = [x for x in p.project_updates.all()]
|
pu = [x for x in p.project_updates.all()]
|
||||||
iu = [x for x in ii.inventory_updates.all()]
|
iu = [x for x in ii.inventory_updates.all()]
|
||||||
assert len(pu) == 1
|
assert len(pu) == 1
|
||||||
|
|||||||
@@ -314,15 +314,15 @@ class TestInstanceGroupOrdering:
|
|||||||
# API does not allow setting IGs on inventory source, so ignore those
|
# API does not allow setting IGs on inventory source, so ignore those
|
||||||
assert iu.preferred_instance_groups == [ig_inv, ig_org]
|
assert iu.preferred_instance_groups == [ig_inv, ig_org]
|
||||||
|
|
||||||
def test_project_update_instance_groups(self, instance_group_factory, project, default_instance_group):
|
def test_project_update_instance_groups(self, instance_group_factory, project, controlplane_instance_group):
|
||||||
pu = ProjectUpdate.objects.create(project=project, organization=project.organization)
|
pu = ProjectUpdate.objects.create(project=project, organization=project.organization)
|
||||||
assert pu.preferred_instance_groups == [default_instance_group]
|
assert pu.preferred_instance_groups == [controlplane_instance_group]
|
||||||
ig_org = instance_group_factory("OrgIstGrp", [default_instance_group.instances.first()])
|
ig_org = instance_group_factory("OrgIstGrp", [controlplane_instance_group.instances.first()])
|
||||||
ig_tmp = instance_group_factory("TmpIstGrp", [default_instance_group.instances.first()])
|
ig_tmp = instance_group_factory("TmpIstGrp", [controlplane_instance_group.instances.first()])
|
||||||
project.organization.instance_groups.add(ig_org)
|
project.organization.instance_groups.add(ig_org)
|
||||||
assert pu.preferred_instance_groups == [ig_org]
|
assert pu.preferred_instance_groups == [ig_org, controlplane_instance_group]
|
||||||
project.instance_groups.add(ig_tmp)
|
project.instance_groups.add(ig_tmp)
|
||||||
assert pu.preferred_instance_groups == [ig_tmp, ig_org]
|
assert pu.preferred_instance_groups == [ig_tmp, ig_org, controlplane_instance_group]
|
||||||
|
|
||||||
def test_job_instance_groups(self, instance_group_factory, inventory, project, default_instance_group):
|
def test_job_instance_groups(self, instance_group_factory, inventory, project, default_instance_group):
|
||||||
jt = JobTemplate.objects.create(inventory=inventory, project=project)
|
jt = JobTemplate.objects.create(inventory=inventory, project=project)
|
||||||
|
|||||||
Reference in New Issue
Block a user