mirror of
https://github.com/ansible/awx.git
synced 2026-02-27 07:56:06 -03:30
Instance has gone lost, and jobs are still either running or waiting inside of its instance group RBAC - user does not have permission to see some of the groups that would be used in the capacity calculation For some cases, a naive capacity dictionary is returned, main goal is to not throw errors and avoid unpredicted behavior Detailed capacity tests are moved into new unit test file.
136 lines
4.4 KiB
Python
136 lines
4.4 KiB
Python
import pytest
|
|
|
|
from awx.main.models import InstanceGroup
|
|
|
|
|
|
class FakeObject(object):
|
|
def __init__(self, **kwargs):
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
|
|
class Job(FakeObject):
|
|
task_impact = 43
|
|
|
|
def log_format(self):
|
|
return 'job 382 (fake)'
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_cluster():
|
|
def stand_up_cluster():
|
|
|
|
class Instances(FakeObject):
|
|
def add(self, *args):
|
|
for instance in args:
|
|
self.obj.instance_list.append(instance)
|
|
|
|
def all(self):
|
|
return self.obj.instance_list
|
|
|
|
class InstanceGroup(FakeObject):
|
|
|
|
def __init__(self, **kwargs):
|
|
super(InstanceGroup, self).__init__(**kwargs)
|
|
self.instance_list = []
|
|
|
|
@property
|
|
def instances(self):
|
|
mgr = Instances(obj=self)
|
|
return mgr
|
|
|
|
|
|
class Instance(FakeObject):
|
|
pass
|
|
|
|
|
|
ig_small = InstanceGroup(name='ig_small')
|
|
ig_large = InstanceGroup(name='ig_large')
|
|
tower = InstanceGroup(name='tower')
|
|
i1 = Instance(hostname='i1', capacity=200)
|
|
i2 = Instance(hostname='i2', capacity=200)
|
|
i3 = Instance(hostname='i3', capacity=200)
|
|
ig_small.instances.add(i1)
|
|
ig_large.instances.add(i2, i3)
|
|
tower.instances.add(i2)
|
|
return [tower, ig_large, ig_small]
|
|
return stand_up_cluster
|
|
|
|
|
|
def test_committed_capacity(sample_cluster):
|
|
tower, ig_large, ig_small = sample_cluster()
|
|
tasks = [
|
|
Job(status='waiting', instance_group=tower),
|
|
Job(status='waiting', instance_group=ig_large),
|
|
Job(status='waiting', instance_group=ig_small)
|
|
]
|
|
capacities = InstanceGroup.objects.capacity_values(
|
|
qs=[tower, ig_large, ig_small], tasks=tasks, breakdown=True
|
|
)
|
|
# Jobs submitted to either tower or ig_larg must count toward both
|
|
assert capacities['tower']['committed_capacity'] == 43 * 2
|
|
assert capacities['ig_large']['committed_capacity'] == 43 * 2
|
|
assert capacities['ig_small']['committed_capacity'] == 43
|
|
|
|
|
|
def test_running_capacity(sample_cluster):
|
|
tower, ig_large, ig_small = sample_cluster()
|
|
tasks = [
|
|
Job(status='running', execution_node='i1'),
|
|
Job(status='running', execution_node='i2'),
|
|
Job(status='running', execution_node='i3')
|
|
]
|
|
capacities = InstanceGroup.objects.capacity_values(
|
|
qs=[tower, ig_large, ig_small], tasks=tasks, breakdown=True
|
|
)
|
|
# Tower is only given 1 instance
|
|
assert capacities['tower']['running_capacity'] == 43
|
|
# Large IG has 2 instances
|
|
assert capacities['ig_large']['running_capacity'] == 43 * 2
|
|
assert capacities['ig_small']['running_capacity'] == 43
|
|
|
|
|
|
def test_offline_node_running(sample_cluster):
|
|
"""
|
|
Assure that algorithm doesn't explode if a job is marked running
|
|
in an offline node
|
|
"""
|
|
tower, ig_large, ig_small = sample_cluster()
|
|
ig_small.instance_list[0].capacity = 0
|
|
tasks = [Job(status='running', execution_node='i1', instance_group=ig_small)]
|
|
capacities = InstanceGroup.objects.capacity_values(
|
|
qs=[tower, ig_large, ig_small], tasks=tasks)
|
|
assert capacities['ig_small']['consumed_capacity'] == 43
|
|
|
|
|
|
def test_offline_node_waiting(sample_cluster):
|
|
"""
|
|
Same but for a waiting job
|
|
"""
|
|
tower, ig_large, ig_small = sample_cluster()
|
|
ig_small.instance_list[0].capacity = 0
|
|
tasks = [Job(status='waiting', instance_group=ig_small)]
|
|
capacities = InstanceGroup.objects.capacity_values(
|
|
qs=[tower, ig_large, ig_small], tasks=tasks)
|
|
assert capacities['ig_small']['consumed_capacity'] == 43
|
|
|
|
|
|
def test_RBAC_reduced_filter(sample_cluster):
|
|
"""
|
|
User can see jobs that are running in `ig_small` and `ig_large` IGs,
|
|
but user does not have permission to see those actual instance groups.
|
|
Verify that this does not blow everything up.
|
|
"""
|
|
tower, ig_large, ig_small = sample_cluster()
|
|
tasks = [
|
|
Job(status='waiting', instance_group=tower),
|
|
Job(status='waiting', instance_group=ig_large),
|
|
Job(status='waiting', instance_group=ig_small)
|
|
]
|
|
capacities = InstanceGroup.objects.capacity_values(
|
|
qs=[tower], tasks=tasks, breakdown=True
|
|
)
|
|
# Cross-links between groups not visible to current user,
|
|
# so a naieve accounting of capacities is returned instead
|
|
assert capacities['tower']['committed_capacity'] == 43
|