-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
migrations: add migration script for Node model changes
Sync DB to model changes after these commits: api.models: basic definitions of Node submodels api.main: use node endpoints for all type of Node subtypes api.db: remove regression collection Signed-off-by: Ricardo Cañuelo <[email protected]>
- Loading branch information
Ricardo Cañuelo
committed
Jan 11, 2024
1 parent
de5ab1b
commit 6ba0677
Showing
1 changed file
with
134 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
# SPDX-License-Identifier: LGPL-2.1-or-later | ||
# | ||
# Copyright (C) 2023 Collabora Limited | ||
# Author: Ricardo Cañuelo <[email protected]> | ||
|
||
"""Migration for Node objects to comply with the models after commits: | ||
api.models: basic definitions of Node submodels | ||
api.main: use node endpoints for all type of Node subtypes | ||
api.db: remove regression collection | ||
""" | ||
|
||
from bson.objectid import ObjectId | ||
|
||
name = '20231215122000_node_models' | ||
dependencies = ['20231102101356_user'] | ||
|
||
|
||
def node_upgrade_needed(node): | ||
"""Checks if a DB Node passed as a parameter needs to be migrated | ||
with this script. | ||
Parameters: | ||
user: a mongodb document (dict) defining a KernelCI Node | ||
Returns: | ||
True if the node needs to be migrated, False otherwise | ||
""" | ||
# The existence of a 'revision' key seems to be enough to detect a | ||
# pre-migration Node | ||
if 'revision' in node: | ||
Check warning on line 33 in migrations/20231215122000_node_models.py GitHub Actions / Lint
|
||
return True | ||
else: | ||
return False | ||
|
||
|
||
def upgrade(db: "pymongo.database.Database"): | ||
Check warning on line 39 in migrations/20231215122000_node_models.py GitHub Actions / Lint
|
||
# Update nodes | ||
nodes = db.node.find() | ||
for node in nodes: | ||
if not node_upgrade_needed(node): | ||
continue | ||
if not node.get('data'): | ||
# Initialize 'data' field if it's empty: a generic Node | ||
# with no specific type may have an emtpy 'data' field | ||
db.node.update_one( | ||
{'_id': node['_id']}, | ||
{'$set': {'data': {}}} | ||
) | ||
# move 'revision' to 'data.kernel_revision' | ||
db.node.update_one( | ||
{'_id': node['_id']}, | ||
{ | ||
'$set': { | ||
'data.kernel_revision': node['revision'] | ||
}, | ||
'$unset': {'revision': ''} | ||
} | ||
) | ||
|
||
# Re-format regressions: move them from "regression" to "node" | ||
regressions = db.regression.find() | ||
for regression in regressions: | ||
db.node.insert_one( | ||
{ | ||
'name': regression.get('name'), | ||
'group': regression.get('group'), | ||
'path': regression.get('path'), | ||
'kind': 'regression', | ||
'data': { | ||
'pass_node': ObjectId(regression['regression_data'][0]), | ||
'fail_node': ObjectId(regression['regression_data'][1]) | ||
}, | ||
'artifacts': regression.get('artifacts'), | ||
'created': regression.get('created'), | ||
'updated': regression.get('updated'), | ||
'timeout': regression.get('timeout'), | ||
'owner': regression.get('owner'), | ||
} | ||
) | ||
db.regression.delete_one({'_id': regression['_id']}) | ||
|
||
|
||
def downgrade(db: 'pymongo.database.Database'): | ||
Check warning on line 86 in migrations/20231215122000_node_models.py GitHub Actions / Lint
|
||
# Move regressions back to "regression" | ||
regressions = db.node.find({'kind': 'regression'}) | ||
for regression in regressions: | ||
fail_node = db.node.find_one( | ||
{'_id': ObjectId(regression['data']['fail_node'])} | ||
) | ||
db.regression.insert_one( | ||
{ | ||
'name': regression.get('name'), | ||
'group': regression.get('group'), | ||
'path': regression.get('path'), | ||
'kind': 'regression', | ||
'parent': regression['data']['fail_node'], | ||
'regression_data': [ | ||
regression['data']['pass_node'], | ||
regression['data']['fail_node'] | ||
], | ||
'revision': fail_node['data']['kernel_revision'], | ||
'artifacts': regression.get('artifacts'), | ||
'created': regression.get('created'), | ||
'updated': regression.get('updated'), | ||
'timeout': regression.get('timeout'), | ||
'owner': regression.get('owner'), | ||
} | ||
) | ||
db.node.delete_one({'_id': regression['_id']}) | ||
|
||
# Downgrade node format | ||
nodes = db.node.find() | ||
for node in nodes: | ||
if not node_upgrade_needed(node): | ||
# move 'data.kernel_revision' to 'revision' | ||
db.node.update_one( | ||
{'_id': node['_id']}, | ||
{ | ||
'$set': { | ||
'revision': node['data']['kernel_revision'] | ||
}, | ||
'$unset': {'data.kernel_revision': ''} | ||
} | ||
) | ||
# unset 'data' if it's empty | ||
node['data'].pop('kernel_revision', None) | ||
if len(node['data']) == 0: | ||
db.node.update_one( | ||
{'_id': node['_id']}, | ||
{'$unset': {'data': ''}} | ||
) |