diff --git a/packageship/.gitignore b/packageship/.gitignore index 04ed6add965a0e5e4c3397a2060bb6ce8e10c1ba..2027f52cd9ebda8e294616082ebbf3cec258f56a 100644 --- a/packageship/.gitignore +++ b/packageship/.gitignore @@ -1,2 +1,4 @@ .DS_Store -*/.DS_Store \ No newline at end of file +*/.DS_Store +*.pyc +*.vscode \ No newline at end of file diff --git a/packageship/packageship/application/apps/package/function/be_depend.py b/packageship/packageship/application/apps/package/function/be_depend.py new file mode 100644 index 0000000000000000000000000000000000000000..e1b7c58dfbb0ec92666b0e23c500fe5ea5b9a3fa --- /dev/null +++ b/packageship/packageship/application/apps/package/function/be_depend.py @@ -0,0 +1,196 @@ +# -*- coding:utf-8 -*- +''' + The dependencies of the query package + Used for package deletion and upgrade scenarios + This includes both install and build dependencies +''' +from sqlalchemy import text +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.sql import literal_column +from flask import current_app +from packageship.libs.dbutils import DBHelper +from packageship.application.models.package import src_pack +from packageship.application.apps.package.function.constants import ResponseCode + +class BeDepend: + ''' + Find the dependencies of the source package + ''' + + def __init__(self, source_name, db_name, with_sub_pack): + ''' + :param source_name: source_name + :param db_name: db_name + :param with_sub_pack: with_sub_pack + ''' + self.source_name = source_name + self.db_name = db_name + self.with_sub_pack = with_sub_pack + # Source package lookup set + self.source_name_set = set() + # Bin package lookup set + self.bin_name_set = set() + # return json + self.result_dict = dict() + + def main(self): + ''' + Map the database, if the source package of the query is not in the database, + throw an exception. Directly to the end + :return: + ''' + with DBHelper(db_name=self.db_name) as data_base: + src_obj = data_base.session.query( + src_pack).filter_by(name=self.source_name).first() + if src_obj: + # spell dictionary + self.result_dict[self.source_name + "_src"] = [ + "source", + src_obj.version, + self.db_name, + [["root", None]] + ] + self.source_name_set.add(self.source_name) + self.package_bedepend( + [src_obj.id], data_base, package_type='src') + + return self.result_dict + + def package_bedepend(self, pkg_id_list, data_base, package_type): + ''' + Query the dependent function + :param pkg_id_list:source or binary packages id + :param data_base: database + :param package_type: package type + :return: + ''' + search_set = set(pkg_id_list) + id_in = literal_column('id').in_(search_set) + # package_type + if package_type == 'src': + sql_str = text(""" + SELECT b1.name AS search_bin_name, + b1.version AS search_bin_version, + src.NAME AS source_name, + b2.name AS bin_name, + b2.id AS bin_id, + s1.name AS bebuild_src_name, + s1.id AS bebuild_src_id, + s2.name AS install_depend_src_name, + s2.id AS install_depend_src_id + FROM + ( SELECT id,NAME FROM src_pack WHERE {} ) src + LEFT JOIN bin_pack b1 ON b1.srcIDkey = src.id + LEFT JOIN pack_provides ON pack_provides.binIDkey = b1.id + LEFT JOIN pack_requires ON pack_requires.depProIDkey = pack_provides.id + LEFT JOIN src_pack s1 ON s1.id = pack_requires.srcIDkey + LEFT JOIN bin_pack b2 ON b2.id = pack_requires.binIDkey + LEFT JOIN src_pack s2 ON s2.id = b2.srcIDkey;""".format(id_in)) + if package_type == 'bin': + sql_str = text(""" + SELECT b1.name AS search_bin_name, + b1.version AS search_bin_version, + s3.NAME AS source_name, + b2.name AS bin_name, + b2.id AS bin_id, + s1.name AS bebuild_src_name, + s1.id AS bebuild_src_id, + s2.name AS install_depend_src_name, + s2.id AS install_depend_src_id + FROM + (SELECT id,NAME,version,srcIDkey FROM bin_pack WHERE {} ) b1 + LEFT JOIN src_pack s3 ON s3.id = b1.srcIDkey + LEFT JOIN pack_provides ON pack_provides.binIDkey = b1.id + LEFT JOIN pack_requires ON pack_requires.depProIDkey = pack_provides.id + LEFT JOIN src_pack s1 ON s1.id = pack_requires.srcIDkey + LEFT JOIN bin_pack b2 ON b2.id = pack_requires.binIDkey + LEFT JOIN src_pack s2 ON s2.id = b2.srcIDkey; + """.format(id_in)) + try: + result = data_base.session.execute( + sql_str, { + 'id_{}'.format(i): v for i, v in enumerate( + search_set, 1)}).fetchall() + except SQLAlchemyError as sql_err: + current_app.logger.error(sql_err) + return ResponseCode.response_json(ResponseCode.CONNECT_DB_ERROR) + + if result is None: + return + # Source and binary packages that were found to be dependent + source_id_list = [] + bin_id_list = [] + for obj in result: + if obj.source_name is None: + source_name = 'NOT FOUND' + else: + source_name = obj.source_name + if obj.bebuild_src_name: + # Determine if the source package has been checked + if obj.bebuild_src_name not in self.source_name_set: + self.source_name_set.add(obj.bebuild_src_name) + source_id_list.append(obj.bebuild_src_id) + + parent_node = obj.bebuild_src_name + be_type = "build" + # Call the spell dictionary function + self.make_dicts( + obj.search_bin_name, + source_name, + obj.search_bin_version, + parent_node, + be_type) + + if obj.bin_name: + # Determine if the bin package has been checked + if obj.bin_name not in self.bin_name_set: + self.bin_name_set.add(obj.bin_name) + bin_id_list.append(obj.bin_id) + + parent_node = obj.bin_name + be_type = "install" + # Call the spell dictionary function + self.make_dicts( + obj.search_bin_name, + source_name, + obj.search_bin_version, + parent_node, + be_type) + # withsubpack=1 + if self.with_sub_pack == "1": + if obj.install_depend_src_name not in self.source_name_set: + self.source_name_set.add( + obj.install_depend_src_name) + source_id_list.append(obj.install_depend_src_id) + + if len(source_id_list) != 0: + self.package_bedepend( + source_id_list, data_base, package_type="src") + if len(bin_id_list) != 0: + self.package_bedepend(bin_id_list, data_base, package_type="bin") + + def make_dicts(self, key, source_name, version, parent_node, be_type): + ''' + :param key: dependent bin name + :param source_name: source name + :param version: version + :param parent_node: Rely on package name + :param be_type: dependent type + :return: + ''' + if key not in self.result_dict: + self.result_dict[key] = [ + source_name, + version, + self.db_name, + [ + [parent_node, + be_type + ] + ] + ] + else: + self.result_dict[key][-1].append([ + parent_node, + be_type + ]) diff --git a/packageship/packageship/application/apps/package/function/searchdb.py b/packageship/packageship/application/apps/package/function/searchdb.py index 81702e656c9d027f70f9af422b2228f30115b2bf..4861b86cdf5ec3784d19c4a6bc0fd88baab1581c 100644 --- a/packageship/packageship/application/apps/package/function/searchdb.py +++ b/packageship/packageship/application/apps/package/function/searchdb.py @@ -13,11 +13,12 @@ from packageship.libs.dbutils import DBHelper from packageship.libs.log import Log from packageship.application.models.package import bin_pack from packageship.libs.exception import ContentNoneException, Error -from packageship.system_config import DATABASE_SUCCESS_FILE +from packageship.system_config import DATABASE_FILE_INFO from .constants import ResponseCode LOGGER = Log(__name__) + class SearchDB(): """ Description: query in database @@ -57,7 +58,8 @@ class SearchDB(): binary_list.remove(None) search_set = set(binary_list) if not search_set: - LOGGER.logger.warning("The input is None, please check the input value.") + LOGGER.logger.warning( + "The input is None, please check the input value.") return result_list for db_name, data_base in self.db_object_dict.items(): try: @@ -317,7 +319,7 @@ def db_priority(): return dbprioty """ try: - with open(DATABASE_SUCCESS_FILE, 'r', encoding='utf-8') as file_context: + with open(DATABASE_FILE_INFO, 'r', encoding='utf-8') as file_context: init_database_date = yaml.load( file_context.read(), Loader=yaml.FullLoader) diff --git a/packageship/packageship/application/apps/package/view.py b/packageship/packageship/application/apps/package/view.py index 0e1f76302cd159036d836541af2fe71eef57048c..72c1600f6cd767e90c12bfa5cdebfaa7c156051f 100644 --- a/packageship/packageship/application/apps/package/view.py +++ b/packageship/packageship/application/apps/package/view.py @@ -14,7 +14,7 @@ from packageship.libs.exception import Error from packageship.libs.exception import ContentNoneException from packageship.libs.exception import DataMergeException from packageship.libs.log import Log -from packageship.system_config import DATABASE_SUCCESS_FILE +from packageship.system_config import DATABASE_FILE_INFO from .function.constants import ResponseCode from .function.packages import get_packages from .function.packages import update_single_package @@ -36,6 +36,7 @@ from .serialize import have_err_db_name LOGGER = Log(__name__) #pylint: disable = no-self-use + class Packages(Resource): ''' Description: interface for package info management @@ -440,7 +441,7 @@ class Repodatas(Resource): changeLog: ''' try: - with open(DATABASE_SUCCESS_FILE, 'r', encoding='utf-8') as file_context: + with open(DATABASE_FILE_INFO, 'r', encoding='utf-8') as file_context: init_database_date = yaml.load( file_context.read(), Loader=yaml.FullLoader) if init_database_date is None: diff --git a/packageship/packageship/application/initsystem/data_import.py b/packageship/packageship/application/initsystem/data_import.py index eebd0969701d4be100530ab38a77ac38d757a760..e7dafde27c2e97a506efed9b1b1eaf5f8d58d5a7 100644 --- a/packageship/packageship/application/initsystem/data_import.py +++ b/packageship/packageship/application/initsystem/data_import.py @@ -20,7 +20,7 @@ from packageship.application.models.temporarydb import src_requires from packageship.application.models.temporarydb import bin_package from packageship.application.models.temporarydb import bin_requiresment from packageship.application.models.temporarydb import bin_provides -from packageship.system_config import DATABASE_SUCCESS_FILE +from packageship.system_config import DATABASE_FILE_INFO from packageship.system_config import DATABASE_FOLDER_PATH LOGGER = Log(__name__) @@ -74,7 +74,9 @@ class InitDataBase(): 'The content of the database initialization configuration file cannot be empty') if not isinstance(init_database_config, list): raise TypeError('wrong type of configuration file') - + for config_item in init_database_config: + if not isinstance(config_item, dict): + raise TypeError('wrong type of configuration file') return init_database_config def init_data(self): @@ -101,14 +103,14 @@ class InitDataBase(): 'maintenance.information').create_datum_database() for database in self.config_file_datas: - if not isinstance(database, dict): - continue if not database.get('dbname'): continue priority = database.get('priority') if not isinstance(priority, int) or priority < 0 or priority > 100: continue status = database.get('status') + if status not in ['enable', 'disable']: + continue # Initialization data self._init_data(database) @@ -496,9 +498,9 @@ class InitDataBase(): priority: priority ''' try: - if not os.path.exists(DATABASE_SUCCESS_FILE): - pathlib.Path(DATABASE_SUCCESS_FILE).touch() - with open(DATABASE_SUCCESS_FILE, 'a+', encoding='utf8') as file_context: + if not os.path.exists(DATABASE_FILE_INFO): + pathlib.Path(DATABASE_FILE_INFO).touch() + with open(DATABASE_FILE_INFO, 'a+', encoding='utf8') as file_context: setting_content = [] if 'database_content' in Kwargs.keys(): content = Kwargs.get('database_content') @@ -521,8 +523,8 @@ class InitDataBase(): modify record: ''' try: - if os.path.exists(DATABASE_SUCCESS_FILE): - os.remove(DATABASE_SUCCESS_FILE) + if os.path.exists(DATABASE_FILE_INFO): + os.remove(DATABASE_FILE_INFO) except (IOError, Error) as exception_msg: LOGGER.logger.error(exception_msg) return False @@ -542,14 +544,14 @@ class InitDataBase(): if del_result: try: - file_read = open(DATABASE_SUCCESS_FILE, 'r', encoding='utf-8') + file_read = open(DATABASE_FILE_INFO, 'r', encoding='utf-8') _databases = yaml.load( file_read.read(), Loader=yaml.FullLoader) for database in _databases: if database.get('database_name') == db_name: _databases.remove(database) # Delete the successfully imported database configuration node - with open(DATABASE_SUCCESS_FILE, 'w+', encoding='utf-8') as file_context: + with open(DATABASE_FILE_INFO, 'w+', encoding='utf-8') as file_context: yaml.safe_dump(_databases, file_context) except (IOError, Error) as del_config_error: LOGGER.logger.error(del_config_error) diff --git a/packageship/packageship/system_config.py b/packageship/packageship/system_config.py index 8db61286c71e54c52710cb058498052915af731e..e5a0d53d3a5322df3b0d30351a7bf3da3c19095e 100644 --- a/packageship/packageship/system_config.py +++ b/packageship/packageship/system_config.py @@ -19,11 +19,8 @@ SYS_CONFIG_PATH = os.path.join('/', 'etc', 'pkgship', 'package.ini') # data file after successful data import -# DATABASE_SUCCESS_FILE = os.path.join( -# BASE_PATH, 'application', 'initsystem', 'import_success_databse.yaml') - -DATABASE_SUCCESS_FILE = os.path.join( - '/', 'var', 'run', 'import_success_database.yaml') +DATABASE_FILE_INFO = os.path.join( + '/', 'var', 'run', 'database_file_info.yaml') # If the path of the imported database is not specified in the configuration file, the # configuration in the system is used by default diff --git a/packageship/test/test_install_depend.py b/packageship/test/test_install_depend.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391