Skip to content

Commit

Permalink
Merge pull request #100 from naved001/sync-users
Browse files Browse the repository at this point in the history
Sync users with `validate_allocations` command
  • Loading branch information
jtriley authored May 12, 2023
2 parents b7724a6 + 5b9fbd7 commit 2b72869
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-py39-functional-microshift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
env:
PYTHONWARNINGS: ignore
KUBECONFIG: ${{ github.workspace }}/kubeconfig
ACCT_MGT_VERSION: "acd4f462104de6cb8af46baecff2ed968612742d"
ACCT_MGT_VERSION: "44f8f13e4d876249ed2ee1a77fbac86dfd8b3960"

jobs:
build:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
from coldfront_plugin_cloud import openstack
from coldfront_plugin_cloud import openshift
from coldfront_plugin_cloud import utils
from coldfront_plugin_cloud import tasks

from django.core.management.base import BaseCommand, CommandError
from coldfront.core.resource.models import (Resource,
ResourceType)
from coldfront.core.allocation.models import (Allocation,
AllocationStatusChoice)
AllocationStatusChoice,
AllocationUser)
from keystoneauth1.exceptions import http


Expand All @@ -24,6 +26,31 @@ def add_arguments(self, parser):
parser.add_argument('--apply', action='store_true',
help='Apply expected state if validation fails.')

@staticmethod
def sync_users(project_id, allocation, allocator, apply):
coldfront_users = AllocationUser.objects.filter(allocation=allocation, status__name='Active')
allocation_users = allocator.get_users(project_id)
failed_validation = False

# Create users that exist in coldfront but not in the resource
for coldfront_user in coldfront_users:
if coldfront_user.user.username not in allocation_users:
failed_validation = True
logger.warn(f"{coldfront_user.user.username} is not part of {project_id}")
if apply:
tasks.add_user_to_allocation(coldfront_user.pk)

# remove users that are in the resource but not in coldfront
users = set([coldfront_user.user.username for coldfront_user in coldfront_users])
for allocation_user in allocation_users:
if allocation_user not in users:
failed_validation = True
logger.warn(f"{allocation_user} exists in the resource {project_id} but not in coldfront")
if apply:
allocator.remove_role_from_user(allocation_user, project_id)

return failed_validation

def handle(self, *args, **options):

# Openstack Resources first
Expand Down Expand Up @@ -61,6 +88,9 @@ def handle(self, *args, **options):
continue

quota = allocator.get_quota(project_id)

failed_validation = Command.sync_users(project_id, allocation, allocator, options["apply"])

for attr in attributes.ALLOCATION_QUOTA_ATTRIBUTES:
if 'OpenStack' in attr:
key = openstack.QUOTA_KEY_MAPPING_ALL_KEYS.get(attr, None)
Expand Down Expand Up @@ -130,6 +160,8 @@ def handle(self, *args, **options):

quota = allocator.get_quota(project_id)["Quota"]

failed_validation = Command.sync_users(project_id, allocation, allocator, options["apply"])

for attr in attributes.ALLOCATION_QUOTA_ATTRIBUTES:
if "OpenShift" in attr:
key_with_lambda = openshift.QUOTA_KEY_MAPPING.get(attr, None)
Expand Down
5 changes: 5 additions & 0 deletions src/coldfront_plugin_cloud/openshift.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,8 @@ def _delete_user(self, username):
url = f"{self.auth_url}/users/{username}"
r = self.session.delete(url)
return self.check_response(r)

def get_users(self, project_id):
url = f"{self.auth_url}/projects/{project_id}/users"
r = self.session.get(url)
return set(self.check_response(r))
10 changes: 10 additions & 0 deletions src/coldfront_plugin_cloud/openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,13 @@ def create_project_defaults(self, project_id):
else:
logger.info(f'No public network configured. Skipping default '
f'network creation for project {project_id}.')

def get_users(self, project_id):
""" Return users with a role in a project"""
role_name = self.resource.get_attribute(attributes.RESOURCE_ROLE)
role = self.identity.roles.find(name=role_name)
role_assignments = self.identity.role_assignments.list(role=role.id,
project=project_id,
include_names=True)
user_names = set(role_assignment.user["name"] for role_assignment in role_assignments)
return user_names
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import time
import unittest
import uuid

from coldfront_plugin_cloud import attributes, openshift, tasks, utils
from coldfront_plugin_cloud.tests import base
Expand Down Expand Up @@ -77,12 +78,32 @@ def test_add_remove_user(self):
allocator._get_role(user.username, project_id)
allocator._get_role(user2.username, project_id)

assert set([user.username, user2.username]) == allocator.get_users(project_id)

tasks.remove_user_from_allocation(allocation_user2.pk)

allocator._get_role(user.username, project_id)
with self.assertRaises(openshift.NotFound):
allocator._get_role(user2.username, project_id)

assert set([user.username]) == allocator.get_users(project_id)

# use the validate_allocations command to add a new user
user3 = self.new_user()
allocation_user3 = self.new_allocation_user(allocation, user3)
assert user3.username not in allocator.get_users(project_id)
call_command('validate_allocations', apply=True)
assert user3.username in allocator.get_users(project_id)

# directly add a user to openshift which should then be
# deleted when validate_allocations is called
non_coldfront_user = uuid.uuid4().hex
allocator.get_or_create_federated_user(non_coldfront_user)
allocator.assign_role_on_user(non_coldfront_user, project_id)
assert non_coldfront_user in allocator.get_users(project_id)
call_command('validate_allocations', apply=True)
assert non_coldfront_user not in allocator.get_users(project_id)

def test_new_allocation_quota(self):
user = self.new_user()
project = self.new_project(pi=user)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import unittest
import uuid

from coldfront_plugin_cloud import attributes, openstack, tasks, utils
from coldfront_plugin_cloud.tests import base
Expand Down Expand Up @@ -257,13 +258,31 @@ def test_add_remove_user(self):

self.assertEqual(len(roles), 1)
self.assertEqual(roles[0].role['id'], self.role_member.id)
assert set([user.username, user2.username]) == allocator.get_users(project_id)

tasks.remove_user_from_allocation(allocation_user2.pk)

roles = self.identity.role_assignments.list(user=openstack_user.id,
project=openstack_project.id)

self.assertEqual(len(roles), 0)
assert set([user.username]) == allocator.get_users(project_id)

# use the validate_allocations command to add a new user
user3 = self.new_user()
allocation_user3 = self.new_allocation_user(allocation, user3)
assert user3.username not in allocator.get_users(project_id)
call_command('validate_allocations', apply=True)
assert user3.username in allocator.get_users(project_id)

# directly add a user to openstack which should then be
# deleted when validate_allocations is called
non_coldfront_user = uuid.uuid4().hex
allocator.get_or_create_federated_user(non_coldfront_user)
allocator.assign_role_on_user(non_coldfront_user, project_id)
assert non_coldfront_user in allocator.get_users(project_id)
call_command('validate_allocations', apply=True)
assert non_coldfront_user not in allocator.get_users(project_id)

def test_add_remove_user_existing(self):
user = self.new_user()
Expand Down

0 comments on commit 2b72869

Please sign in to comment.