harbor/make/photon/prepare/utils/migration.py
DQ 4617e0ff38 Enhance: Support multi downversion in migration
1. Change down version to list to accept multi verstion value
2. Update search function use BFS to find migration path
2. Add test case

Signed-off-by: DQ <dengq@vmware.com>
2020-07-07 21:36:58 +08:00

66 lines
2.1 KiB
Python

import yaml
import click
import importlib
import os
from collections import deque
class MigratioNotFound(Exception): ...
class MigrationVersion:
'''
The version used to migration
Arttribute:
name(str): version name like `1.0.0`
module: the python module object for a specific migration which contains migrate info, codes and templates
down_versions(list): previous versions that can migrated to this version
'''
def __init__(self, version: str):
self.name = version
self.module = importlib.import_module("migrations.version_{}".format(version.replace(".","_")))
@property
def down_versions(self):
return self.module.down_revisions
def read_conf(path):
with open(path) as f:
try:
d = yaml.safe_load(f)
except Exception as e:
click.echo("parse config file err, make sure your harbor config version is above 1.8.0", e)
exit(-1)
return d
def search(input_version: str, target_version: str) -> list :
"""
Find the migration path by BFS
Args:
input_version(str): The version migration start from
target_version(str): The target version migrated to
Returns:
list: the module of migrations in the upgrade path
"""
upgrade_path = []
next_version, visited, q = {}, set(), deque()
q.append(target_version)
found = False
while q: # BFS to find a valid path
version = MigrationVersion(q.popleft())
visited.add(version.name)
if version.name == input_version:
found = True
break # break loop cause migration path found
for v in version.down_versions:
next_version[v] = version.name
if v not in (visited.union(q)):
q.append(v)
if not found:
raise MigratioNotFound('no migration path found to target version')
current_version = MigrationVersion(input_version)
while current_version.name != target_version:
current_version = MigrationVersion(next_version[current_version.name])
upgrade_path.append(current_version)
return list(map(lambda x: x.module, upgrade_path))