migrate_artifact.py
122 lines
| 4.5 KiB
| text/x-python
|
PythonLexer
r5608 | # Copyright (C) 2016-2024 RhodeCode GmbH | |||
r5516 | # | |||
# This program is free software: you can redistribute it and/or modify | ||||
# it under the terms of the GNU Affero General Public License, version 3 | ||||
# (only), as published by the Free Software Foundation. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU Affero General Public License | ||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
# | ||||
# This program is dual-licensed. If you wish to learn more about the | ||||
# RhodeCode Enterprise Edition, including its added features, Support services, | ||||
# and proprietary license terms, please see https://rhodecode.com/licenses/ | ||||
import sys | ||||
import logging | ||||
import click | ||||
from rhodecode.lib.pyramid_utils import bootstrap | ||||
from rhodecode.lib.ext_json import json | ||||
from rhodecode.model.db import FileStore | ||||
from rhodecode.apps.file_store import utils as store_utils | ||||
log = logging.getLogger(__name__) | ||||
@click.command() | ||||
@click.argument('ini_path', type=click.Path(exists=True)) | ||||
@click.argument('file_uid') | ||||
@click.option( | ||||
'--source-backend-conf', | ||||
type=click.Path(exists=True, dir_okay=False, readable=True), | ||||
help='Source backend config file path in a json format' | ||||
) | ||||
@click.option( | ||||
'--dest-backend-conf', | ||||
type=click.Path(exists=True, dir_okay=False, readable=True), | ||||
help='Source backend config file path in a json format' | ||||
) | ||||
def main(ini_path, file_uid, source_backend_conf, dest_backend_conf): | ||||
return command(ini_path, file_uid, source_backend_conf, dest_backend_conf) | ||||
_source_settings = {} | ||||
_dest_settings = {} | ||||
def command(ini_path, file_uid, source_backend_conf, dest_backend_conf): | ||||
with bootstrap(ini_path, env={'RC_CMD_SETUP_RC': '1'}) as env: | ||||
migrate_func(env, file_uid, source_backend_conf, dest_backend_conf) | ||||
def migrate_func(env, file_uid, source_backend_conf=None, dest_backend_conf=None): | ||||
""" | ||||
Example usage:: | ||||
from rhodecode.lib.rc_commands import migrate_artifact | ||||
migrate_artifact._source_settings = { | ||||
'file_store.backend.type': 'filesystem_v1', | ||||
'file_store.filesystem_v1.storage_path': '/var/opt/rhodecode_data/file_store', | ||||
} | ||||
migrate_artifact._dest_settings = { | ||||
'file_store.backend.type': 'objectstore', | ||||
'file_store.objectstore.url': 'http://s3-minio:9000', | ||||
'file_store.objectstore.bucket': 'rhodecode-file-store', | ||||
'file_store.objectstore.key': 's3admin', | ||||
'file_store.objectstore.secret': 's3secret4', | ||||
'file_store.objectstore.region': 'eu-central-1', | ||||
} | ||||
for db_obj in FileStore.query().all(): | ||||
migrate_artifact.migrate_func({}, db_obj.file_uid) | ||||
""" | ||||
try: | ||||
from rc_ee.api.views.store_api import _store_file | ||||
except ImportError: | ||||
click.secho('ERROR: Unable to import store_api. ' | ||||
'store_api is only available in EE edition of RhodeCode', | ||||
fg='red') | ||||
sys.exit(-1) | ||||
source_settings = _source_settings | ||||
if source_backend_conf: | ||||
source_settings = json.loads(open(source_backend_conf).read()) | ||||
dest_settings = _dest_settings | ||||
if dest_backend_conf: | ||||
dest_settings = json.loads(open(dest_backend_conf).read()) | ||||
if file_uid.isnumeric(): | ||||
file_store_db_obj = FileStore().query() \ | ||||
.filter(FileStore.file_store_id == file_uid) \ | ||||
.scalar() | ||||
else: | ||||
file_store_db_obj = FileStore().query() \ | ||||
.filter(FileStore.file_uid == file_uid) \ | ||||
.scalar() | ||||
if not file_store_db_obj: | ||||
click.secho(f'ERROR: Unable to fetch artifact from database file_uid={file_uid}', | ||||
fg='red') | ||||
sys.exit(-1) | ||||
uid_filename = file_store_db_obj.file_uid | ||||
org_filename = file_store_db_obj.file_display_name | ||||
click.secho(f'Attempting to migrate artifact {uid_filename}, filename: {org_filename}', fg='green') | ||||
# get old version of f_store based on the data. | ||||
origin_f_store = store_utils.get_filestore_backend(source_settings, always_init=True) | ||||
reader, metadata = origin_f_store.fetch(uid_filename) | ||||
target_f_store = store_utils.get_filestore_backend(dest_settings, always_init=True) | ||||
target_f_store.import_to_store(reader, org_filename, uid_filename, metadata) | ||||
click.secho(f'Migrated artifact {uid_filename}, filename: {org_filename} into {target_f_store} storage', fg='green') | ||||