From c8cb465fde14ffdedeafdc59f129ede86b7162c9 Mon Sep 17 00:00:00 2001 From: Peter Braun Date: Tue, 9 Jun 2026 15:04:10 +0200 Subject: [PATCH] fix: do not allow exec instances to be added to the control plane (#16477) Co-authored-by: Stevenson Michel --- awx/main/tasks/system.py | 5 +++++ awx/main/tests/functional/test_instances.py | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index fda46b2968..3447edcac8 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -240,12 +240,17 @@ def apply_cluster_membership_policies(): # Process policy instance list first, these will represent manually managed memberships instance_hostnames_map = {inst.hostname: inst for inst in all_instances} for ig in all_groups: + # we don't want to allow execution nodes in the control plane + exclude_type = 'execution' if ig.name == settings.DEFAULT_CONTROL_PLANE_QUEUE_NAME else 'control' group_actual = Group(obj=ig, instances=[], prior_instances=[instance.pk for instance in ig.instances.all()]) # obtained in prefetch for hostname in ig.policy_instance_list: if hostname not in instance_hostnames_map: logger.info("Unknown instance {} in {} policy list".format(hostname, ig.name)) continue inst = instance_hostnames_map[hostname] + if inst.node_type == exclude_type: + logger.info("Instance {} is excluded in {} policy list".format(hostname, ig.name)) + continue group_actual.instances.append(inst.id) # NOTE: arguable behavior: policy-list-group is not added to # instance's group count for consideration in minimum-policy rules diff --git a/awx/main/tests/functional/test_instances.py b/awx/main/tests/functional/test_instances.py index 4ed652179d..ce0f69d592 100644 --- a/awx/main/tests/functional/test_instances.py +++ b/awx/main/tests/functional/test_instances.py @@ -287,6 +287,20 @@ def test_control_plane_policy_exception(controlplane_instance_group): assert 'foo-1' not in [inst.hostname for inst in controlplane_instance_group.instances.all()] +@pytest.mark.django_db +def test_policy_instance_list_controlplane_excludes_execution_node(controlplane_instance_group): + controlplane_instance_group.policy_instance_percentage = 100 + controlplane_instance_group.save() + exec_inst = Instance.objects.create(hostname='exec-1', node_type='execution') + control_inst = Instance.objects.create(hostname='control-1', node_type='control') + controlplane_instance_group.policy_instance_list = [exec_inst.hostname] + controlplane_instance_group.save() + apply_cluster_membership_policies() + members = list(controlplane_instance_group.instances.all()) + assert exec_inst not in members + assert control_inst in members + + @pytest.mark.django_db def test_normal_instance_group_policy_exception(): ig = InstanceGroup.objects.create(name='bar', policy_instance_percentage=100, policy_instance_minimum=2)