Added CLI command 'maintenance purge_home_projects'
This command soft-deletes home projects when their owning user is no longer there.
This commit is contained in:
parent
bf498b829c
commit
d2a0a5ae26
@ -808,6 +808,19 @@ class PillarServer(BlinkerCompatibleEve):
|
||||
return patch_internal(resource, payload=payload, concurrency_check=concurrency_check,
|
||||
skip_validation=skip_validation, **lookup)[:4]
|
||||
|
||||
def delete_internal(self, resource: str, concurrency_check=False,
|
||||
suppress_callbacks=False, **lookup):
|
||||
"""Workaround for Eve issue https://github.com/nicolaiarocci/eve/issues/810"""
|
||||
from eve.methods.delete import deleteitem_internal
|
||||
|
||||
url = self.config['URLS'][resource]
|
||||
path = '%s/%s/%s' % (self.api_prefix, url, lookup['_id'])
|
||||
with self.__fake_request_url_rule('DELETE', path):
|
||||
return deleteitem_internal(resource,
|
||||
concurrency_check=concurrency_check,
|
||||
suppress_callbacks=suppress_callbacks,
|
||||
**lookup)[:4]
|
||||
|
||||
def _list_routes(self):
|
||||
from pprint import pprint
|
||||
from flask import url_for
|
||||
|
@ -263,6 +263,53 @@ def check_home_project_groups():
|
||||
return bad
|
||||
|
||||
|
||||
@manager_maintenance.option('-g', '--go', dest='go',
|
||||
action='store_true', default=False,
|
||||
help='Actually go and perform the changes, without this just '
|
||||
'shows differences.')
|
||||
def purge_home_projects(go=False):
|
||||
"""Deletes all home projects that have no owner."""
|
||||
from pillar.api.utils.authentication import force_cli_user
|
||||
force_cli_user()
|
||||
|
||||
users_coll = current_app.data.driver.db['users']
|
||||
proj_coll = current_app.data.driver.db['projects']
|
||||
good = bad = 0
|
||||
|
||||
def bad_projects():
|
||||
nonlocal good, bad
|
||||
|
||||
for proj in proj_coll.find({'category': 'home', '_deleted': {'$ne': True}}):
|
||||
pid = proj['_id']
|
||||
uid = proj.get('user')
|
||||
if not uid:
|
||||
log.info('Project %s has no user assigned', uid)
|
||||
bad += 1
|
||||
yield pid
|
||||
continue
|
||||
|
||||
if users_coll.find({'_id': uid, '_deleted': {'$ne': True}}).count() == 0:
|
||||
log.info('Project %s has non-existing owner %s', pid, uid)
|
||||
bad += 1
|
||||
yield pid
|
||||
continue
|
||||
|
||||
good += 1
|
||||
|
||||
if not go:
|
||||
log.info('Dry run, use --go to actually perform the changes.')
|
||||
|
||||
for project_id in bad_projects():
|
||||
log.info('Soft-deleting project %s', project_id)
|
||||
if go:
|
||||
r, _, _, status = current_app.delete_internal('projects', _id=project_id)
|
||||
if status != 204:
|
||||
raise ValueError(f'Error {status} deleting {project_id}: {r}')
|
||||
|
||||
log.info('%i projects OK, %i projects deleted', good, bad)
|
||||
return bad
|
||||
|
||||
|
||||
@manager_maintenance.command
|
||||
@manager_maintenance.option('-c', '--chunk', dest='chunk_size', default=50,
|
||||
help='Number of links to update, use 0 to update all.')
|
||||
|
0
tests/test_cli/__init__.py
Normal file
0
tests/test_cli/__init__.py
Normal file
35
tests/test_cli/test_maintenance.py
Normal file
35
tests/test_cli/test_maintenance.py
Normal file
@ -0,0 +1,35 @@
|
||||
from bson import ObjectId
|
||||
|
||||
from pillar.tests import AbstractPillarTest
|
||||
|
||||
|
||||
class PurgeHomeProjectsTest(AbstractPillarTest):
|
||||
def test_purge(self):
|
||||
self.create_standard_groups()
|
||||
# user_a will be soft-deleted, user_b will be hard-deleted.
|
||||
# We don't support soft-deleting users yet, but the code should be
|
||||
# handling that properly anyway.
|
||||
user_a = self.create_user(user_id=24 * 'a', roles={'subscriber'}, token='token-a')
|
||||
user_b = self.create_user(user_id=24 * 'b', roles={'subscriber'}, token='token-b')
|
||||
|
||||
# GET the home project to create it.
|
||||
home_a = self.get('/api/bcloud/home-project', auth_token='token-a').json()
|
||||
home_b = self.get('/api/bcloud/home-project', auth_token='token-b').json()
|
||||
|
||||
with self.app.app_context():
|
||||
users_coll = self.app.db('users')
|
||||
|
||||
res = users_coll.update_one({'_id': user_a}, {'$set': {'_deleted': True}})
|
||||
self.assertEqual(1, res.modified_count)
|
||||
|
||||
res = users_coll.delete_one({'_id': user_b})
|
||||
self.assertEqual(1, res.deleted_count)
|
||||
|
||||
from pillar.cli.maintenance import purge_home_projects
|
||||
|
||||
with self.app.app_context():
|
||||
self.assertEqual(2, purge_home_projects(go=True))
|
||||
|
||||
proj_coll = self.app.db('projects')
|
||||
self.assertEqual(True, proj_coll.find_one({'_id': ObjectId(home_a['_id'])})['_deleted'])
|
||||
self.assertEqual(True, proj_coll.find_one({'_id': ObjectId(home_b['_id'])})['_deleted'])
|
Loading…
x
Reference in New Issue
Block a user