Merge pull request #1154 from chrismeyersfsu/enhancement-tower_in_all_groups

add all instances to special tower instance group
This commit is contained in:
Chris Meyers 2018-04-02 09:39:04 -04:00 committed by GitHub
commit 47fa99d3ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 56 additions and 12 deletions

View File

@ -231,10 +231,7 @@ class IsSuperUser(permissions.BasePermission):
class InstanceGroupTowerPermission(ModelAccessPermission):
def has_object_permission(self, request, view, obj):
if request.method == 'DELETE' and obj.name == "tower":
return False
if request.method in ['PATCH', 'PUT'] and obj.name == 'tower' and \
request and request.data and request.data.get('name', '') != 'tower':
if request.method not in permissions.SAFE_METHODS and obj.name == "tower":
return False
return super(InstanceGroupTowerPermission, self).has_object_permission(request, view, obj)

View File

@ -113,6 +113,9 @@ class InstanceManager(models.Manager):
# NOTE: TODO: Likely to repurpose this once standalone ramparts are a thing
return "tower"
def all_non_isolated(self):
return self.filter(rampart_groups__controller__isnull=True).distinct()
class InstanceGroupManager(models.Manager):
"""A custom manager class for the Instance model.

View File

@ -163,6 +163,10 @@ class InstanceGroup(models.Model, RelatedJobsMixin):
def _get_related_jobs(self):
return UnifiedJob.objects.filter(instance_group=self)
def add_all_non_iso_instances(self):
self.instances = Instance.objects.all_non_isolated()
self.save()
class Meta:
app_label = 'main'

View File

@ -143,9 +143,13 @@ def apply_cluster_membership_policies(self):
actual_instances = []
Group = namedtuple('Group', ['obj', 'instances'])
Node = namedtuple('Instance', ['obj', 'groups'])
# Add every instnace to the special 'tower' group
InstanceGroup.objects.get(name='tower').add_all_non_iso_instances()
# Process policy instance list first, these will represent manually managed instances
# that will not go through automatic policy determination
for ig in InstanceGroup.objects.all():
for ig in InstanceGroup.objects.exclude(name='tower'):
logger.info(six.text_type("Considering group {}").format(ig.name))
ig.instances.clear()
group_actual = Group(obj=ig, instances=[])
@ -312,7 +316,7 @@ def purge_old_stdout_files(self):
def cluster_node_heartbeat(self):
logger.debug("Cluster node heartbeat task.")
nowtime = now()
instance_list = list(Instance.objects.filter(rampart_groups__controller__isnull=True).distinct())
instance_list = list(Instance.objects.all_non_isolated())
this_inst = None
lost_instances = []

View File

@ -80,12 +80,20 @@ def test_delete_instance_group_jobs_running(delete, instance_group_jobs_running,
@pytest.mark.django_db
def test_delete_tower_instance_group_prevented(delete, options, tower_instance_group, user):
def test_modify_delete_tower_instance_group_prevented(delete, options, tower_instance_group, user, patch, put):
url = reverse("api:instance_group_detail", kwargs={'pk': tower_instance_group.pk})
super_user = user('bob', True)
# DELETE tower group not allowed
delete(url, None, super_user, expect=403)
# OPTIONS should just be "GET"
resp = options(url, None, super_user, expect=200)
actions = ['GET', 'PUT',]
assert 'DELETE' not in resp.data['actions']
for action in actions:
assert action in resp.data['actions']
assert len(resp.data['actions'].keys()) == 1
assert 'GET' in resp.data['actions']
# Updating tower group fields not allowed
patch(url, {'name': 'foobar'}, super_user, expect=403)
patch(url, {'policy_instance_percentage': 40}, super_user, expect=403)
put(url, {'name': 'foobar'}, super_user, expect=403)

View File

@ -162,6 +162,7 @@ def test_instance_group_basic_policies(instance_factory, instance_group_factory)
i2 = instance_factory("i2")
i3 = instance_factory("i3")
i4 = instance_factory("i4")
instance_group_factory("tower")
ig0 = instance_group_factory("ig0")
ig1 = instance_group_factory("ig1", minimum=2)
ig2 = instance_group_factory("ig2", percentage=50)
@ -174,7 +175,7 @@ def test_instance_group_basic_policies(instance_factory, instance_group_factory)
ig2 = InstanceGroup.objects.get(id=ig2.id)
ig3 = InstanceGroup.objects.get(id=ig3.id)
assert len(ig0.instances.all()) == 1
assert i0 in ig0.instances.all()
assert i0 in ig0.instances.all()
assert len(InstanceGroup.objects.get(id=ig1.id).instances.all()) == 2
assert i1 in ig1.instances.all()
assert i2 in ig1.instances.all()

View File

@ -31,15 +31,32 @@ 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_tower_group(mock, instance_factory, instance_group_factory):
instance_factory("i1")
instance_factory("i2")
instance_factory("i3")
ig_t = instance_group_factory("tower")
instance_group_factory("ig1", percentage=25)
instance_group_factory("ig2", percentage=25)
instance_group_factory("ig3", percentage=25)
instance_group_factory("ig4", percentage=25)
apply_cluster_membership_policies()
assert len(ig_t.instances.all()) == 3
@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_t = instance_group_factory("tower")
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_t.instances.all()) == 1
assert len(ig_1.instances.all()) == 1
assert i1 in ig_1.instances.all()
assert len(ig_2.instances.all()) == 1
@ -50,6 +67,7 @@ def test_policy_instance_few_instances(mock, instance_factory, instance_group_fa
assert i1 in ig_4.instances.all()
i2 = instance_factory("i2")
apply_cluster_membership_policies()
assert len(ig_t.instances.all()) == 2
assert len(ig_1.instances.all()) == 1
assert i1 in ig_1.instances.all()
assert len(ig_2.instances.all()) == 1
@ -66,11 +84,13 @@ def test_policy_instance_distribution_uneven(mock, instance_factory, instance_gr
i1 = instance_factory("i1")
i2 = instance_factory("i2")
i3 = instance_factory("i3")
ig_t = instance_group_factory("tower")
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_t.instances.all()) == 3
assert len(ig_1.instances.all()) == 1
assert i1 in ig_1.instances.all()
assert len(ig_2.instances.all()) == 1
@ -88,11 +108,13 @@ def test_policy_instance_distribution_even(mock, instance_factory, instance_grou
i2 = instance_factory("i2")
i3 = instance_factory("i3")
i4 = instance_factory("i4")
ig_t = instance_group_factory("tower")
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_t.instances.all()) == 4
assert len(ig_1.instances.all()) == 1
assert i1 in ig_1.instances.all()
assert len(ig_2.instances.all()) == 1
@ -104,6 +126,7 @@ def test_policy_instance_distribution_even(mock, instance_factory, instance_grou
ig_1.policy_instance_minimum = 2
ig_1.save()
apply_cluster_membership_policies()
assert len(ig_t.instances.all()) == 4
assert len(ig_1.instances.all()) == 2
assert i1 in ig_1.instances.all()
assert i2 in ig_1.instances.all()
@ -122,11 +145,13 @@ def test_policy_instance_distribution_simultaneous(mock, instance_factory, insta
i2 = instance_factory("i2")
i3 = instance_factory("i3")
i4 = instance_factory("i4")
ig_t = instance_group_factory("tower")
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_t.instances.all()) == 4
assert len(ig_1.instances.all()) == 2
assert i1 in ig_1.instances.all()
assert i2 in ig_1.instances.all()
@ -143,11 +168,13 @@ def test_policy_instance_distribution_simultaneous(mock, instance_factory, insta
def test_policy_instance_list_manually_managed(mock, instance_factory, instance_group_factory):
i1 = instance_factory("i1")
i2 = instance_factory("i2")
ig_t = instance_group_factory("tower")
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_t.instances.all()) == 2
assert len(ig_1.instances.all()) == 1
assert i1 in ig_1.instances.all()
assert i2 not in ig_1.instances.all()