def test_resolve_latest(self): deps = DependencyUtils.install( PackageIdentifier.parse_list(["testlatest_1.0"]), APMAP, {}) self.assertEqual(["version_2.0", "testlatest_1.0"], list(map(str, map(IDENTIFIER_GETTER, deps)))) deps = DependencyUtils.install( PackageIdentifier.parse_list(["testlatest_1.0"]), APMAP, filtermap(IPMAP, "version_1.0")) self.assertEqual(["version_2.0", "testlatest_1.0"], list(map(str, map(IDENTIFIER_GETTER, deps)))) deps = DependencyUtils.install( PackageIdentifier.parse_list(["testlatest_1.0"]), APMAP, filtermap(IPMAP, "version_2.0")) self.assertEqual(["testlatest_1.0"], list(map(str, map(IDENTIFIER_GETTER, deps)))) deps = DependencyUtils.prereq( PackageIdentifier.parse_list(["testlatest_2.0"]), APMAP, {}) self.assertEqual(["version_2.0"], list(map(str, map(IDENTIFIER_GETTER, deps)))) deps = DependencyUtils.prereq( PackageIdentifier.parse_list(["testlatest_2.0", "testlatest_2.1"]), APMAP, {}) self.assertEqual(["version_2.0"], list(map(str, map(IDENTIFIER_GETTER, deps))))
def test_depends_install(self): deps = DependencyUtils.install(PackageIdentifier.parse_list([]), self.pm.list_available_packages(), self.pm.list_installed_packages()) self.__assert_deps(deps, [], AvailablePackage) deps = DependencyUtils.install( PackageIdentifier.parse_list(["container-A_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages()) self.__assert_deps(deps, [ "container-E_1.0", "container-B_1.0", "container-C_1.0", "container-A_1.0" ], AvailablePackage) self.pm.install_packages( PackageIdentifier.parse_list(["container-A_1.0"])) deps = DependencyUtils.install( PackageIdentifier.parse_list(["container-A_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages()) self.__assert_deps(deps, [], AvailablePackage) deps = DependencyUtils.install( PackageIdentifier.parse_list(["container-A_2.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages()) self.__assert_deps(deps, ["container-D_1.0", "container-A_2.0"], AvailablePackage)
def test_install(self): deps = DependencyUtils.install(PackageIdentifier.parse_list( ["container-A_1.0", "container-A_2.0"]), APMAP, {}, env=Environment()) self.assertEqual([ "container-E_1.0", "container-B_1.0", "container-C_1.0", "container-A_1.0", "container-D_1.0", "container-A_2.0" ], deps2strlist(deps)) deps = DependencyUtils.install(PackageIdentifier.parse_list( ["container-A_1.0", "container-A_2.0"]), APMAP, filtermap(IPMAP, "container-E_1.0"), env=Environment()) self.assertEqual([ "container-B_1.0", "container-C_1.0", "container-A_1.0", "container-D_1.0", "container-A_2.0" ], deps2strlist(deps))
def test_depends_with_custom_env(self): env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("Custom env", {})) deps = DependencyUtils.install( PackageIdentifier.parse_list(["condition_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages(), env=env ) self.__assert_deps(deps, ["condition-B_1.0", "condition-D_1.0", "condition-F_1.0", "condition-H_1.0", "condition_1.0"], AvailablePackage) self.pm.update_user_environment(set_map={"FOO": "HELLO"}) env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("Custom env", {})) deps = DependencyUtils.install( PackageIdentifier.parse_list(["condition_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages(), env=env ) self.__assert_deps(deps, ["condition-A_1.0", "condition-D_1.0", "condition-F_1.0", "condition-H_1.0", "condition_1.0"], AvailablePackage) self.pm.update_user_environment(set_map={"FOO": "HELLO"}) env = Environment.build(self.pm.build_builtin_environment(), self.pm.build_user_environment(), Environment("Custom env", {"FOO": "BAR"})) deps = DependencyUtils.install( PackageIdentifier.parse_list(["condition_1.0"]), self.pm.list_available_packages(), self.pm.list_installed_packages(), env=env ) self.__assert_deps(deps, ["condition-A_1.0", "condition-C_1.0", "condition-F_1.0", "condition_1.0"], AvailablePackage)
def provision_profile(self, profile): if not profile.folder.is_dir(): # Create folder if needed profile.folder.mkdir(parents=True) else: # Clean folder content for item in profile.folder.glob("*"): if item.is_symlink(): item.unlink() else: shutil.rmtree(str(item)) # Check if all needed packages are installed missing_packages = DependencyUtils.install( profile.packages, self.list_available_packages(), self.list_installed_packages(), env=self.build_pf_environment(profile)) if len(missing_packages) == 0: self.logger.print_verbose("All packages are already installed") else: self.logger.print_default("Profile is out of sync") try: self.install_packages(profile.packages, env=self.build_pf_environment(profile)) except Exception as e: raise ProfileProvisioningException(e) # Do all needed links errors = 0 for ip in self.get_profile_dependencies(profile): pi_folder = profile.folder / ip.identifier.name if pi_folder.exists(): pi_folder = profile.folder / str(ip.identifier) try: env = self.build_pf_environment(profile) self.sync_packages([ip.identifier], env=env) pi_folder.symlink_to(ip.folder) except Exception as e: errors += 1 self.logger.print_error( "Error while sync operation on {ip.identifier}".format( ip=ip)) self.logger.print_error(str(e)) print_trace() # Touch folder when provisionning is done without error if errors == 0: profile.folder.touch(exist_ok=True)
def test_uninstall(self): ipmap = OrderedDict() for ap in DependencyUtils.install( PackageIdentifier.parse_list( ["container-A_1.0", "container-A_2.0"]), APMAP, {}): ipmap[ap.identifier] = IPMAP[ap.identifier] self.assertEqual([ "container-E_1.0", "container-B_1.0", "container-C_1.0", "container-A_1.0", "container-D_1.0", "container-A_2.0" ], deps2strlist(ipmap.values())) deps = DependencyUtils.uninstall( PackageIdentifier.parse_list(["container-A_1.0"]), ipmap) self.assertEqual( ["container-A_1.0", "container-B_1.0", "container-E_1.0"], deps2strlist(deps))
def test_prereq(self): prereqs = DependencyUtils.prereq( PackageIdentifier.parse_list(["pkg-with-prereq_1.0"]), APMAP, {}) self.assertEqual(list(map(str, prereqs)), ["prereq-A_1.0", "prereq-B_1.0"]) for p in prereqs: self.assertTrue(isinstance(p, AvailablePackage)) prereqs = DependencyUtils.prereq( PackageIdentifier.parse_list(["pkg-with-prereq_1.0"]), APMAP, IPMAP) self.assertEqual(list(map(str, prereqs)), ["prereq-A_1.0", "prereq-B_1.0"]) for p in prereqs: self.assertTrue(isinstance(p, InstalledPackage)) prereqs = DependencyUtils.prereq( PackageIdentifier.parse_list(["pkg-with-prereq_2.0"]), APMAP, {}) self.assertEqual(list(map(str, prereqs)), ["prereq-A_1.0", "prereq-B_2.0"]) prereqs = DependencyUtils.prereq( PackageIdentifier.parse_list(["pkg-with-prereq_0.1"]), APMAP, {}) self.assertEqual(list(map(str, prereqs)), ["prereq-A_0.1-fail"]) prereqs = DependencyUtils.prereq( PackageIdentifier.parse_list(["pkg-with-deps-with-prereq_1.0"]), APMAP, {}) self.assertEqual(list(map(str, prereqs)), []) install = DependencyUtils.install( PackageIdentifier.parse_list(["pkg-with-deps-with-prereq_1.0"]), APMAP, {}) prereqs = DependencyUtils.prereq([x.identifier for x in install], APMAP, {}) self.assertEqual(list(map(str, prereqs)), ["prereq-A_1.0", "prereq-B_1.0"])
def _getdeps(env, ipmap): return DependencyUtils.install(PackageIdentifier.parse_list( ["condition_1.0"]), APMAP, ipmap, env=env)
def install_packages(self, pilist: list, env: Environment = None, keep_folder_on_error: bool = False): """ Compute dependency tree, check compatibility, download from remotes and extract needed packages @return: InstalledPackage list """ with self.application_lock.acquire(): prereq_install_folder = None ipmap = self.list_installed_packages() apmap = self.list_available_packages() out = [] # Build env to resolve dynamic dependencies if env is None: env = Environment.build(self.build_builtin_environment(), self.build_user_environment()) try: ap_to_install = DependencyUtils.install(pilist, apmap, ipmap, env=env) # Check leaf min version min_version = check_leaf_min_version(ap_to_install) if min_version: raise LeafOutOfDateException( "You need to upgrade leaf to v{version} to install {text}" .format(version=min_version, text=", ".join([ str(ap.identifier) for ap in ap_to_install ]))) # Check nothing to do if len(ap_to_install) == 0: self.logger.print_default("All packages are installed") else: # Check available size download_totalsize = 0 for ap in ap_to_install: if ap.size is not None: download_totalsize += ap.size fs_check_free_space(self.download_cache_folder, download_totalsize) # Confirm text = ", ".join( [str(ap.identifier) for ap in ap_to_install]) self.logger.print_quiet( "Packages to install: {packages}".format( packages=text)) if download_totalsize > 0: self.logger.print_default( "Total size:", sizeof_fmt(download_totalsize)) self.print_with_confirm(raise_on_decline=True) # Install prereq prereq_to_install = DependencyUtils.prereq(pilist, apmap, ipmap, env=env) if len(prereq_to_install) > 0: self.logger.print_default("Check required packages") prereq_install_folder = mkdir_tmp_leaf_dir() self.install_prereq( [p.identifier for p in prereq_to_install], prereq_install_folder, apmap=apmap, env=env) # Download ap list self.logger.print_default( "Downloading {size} package(s)".format( size=len(ap_to_install))) la_to_install = [] for ap in ap_to_install: la_to_install.append(self.__download_ap(ap)) # Check the extracted size extracted_totalsize = 0 for la in la_to_install: if la.final_size is not None: extracted_totalsize += la.final_size else: extracted_totalsize += la.get_total_size() fs_check_free_space(self.install_folder, extracted_totalsize) # Extract la list for la in la_to_install: self.logger.print_default( "[{current}/{total}] Installing {la.identifier}". format(current=(len(out) + 1), total=len(la_to_install), la=la)) ip = self.__extract_artifact( la, env, self.install_folder, ipmap=ipmap, keep_folder_on_error=keep_folder_on_error) out.append(ip) finally: if not keep_folder_on_error and prereq_install_folder is not None: self.logger.print_verbose( "Remove prereq root folder {folder}".format( folder=prereq_install_folder)) rmtree_force(prereq_install_folder) return out
def install_packages(self, items: list, env: Environment = None, keep_folder_on_error: bool = False): """ Compute dependency tree, check compatibility, download from remotes and extract needed packages @return: InstalledPackage list """ with self.application_lock.acquire(): ipmap = self.list_installed_packages() apmap = self.list_available_packages() pilist = [] for item in items: if isinstance(item, PackageIdentifier): # Package identifier is given pilist.append(item) elif PackageIdentifier.is_valid_identifier(item): # Package identifier string given pilist.append(PackageIdentifier.parse(item)) else: # If leaf artifacts are given, add/replace identifiers of available packages la = LeafArtifact(Path(item)) pilist.append(la.identifier) apmap[la.identifier] = la out = [] # Build env to resolve dynamic dependencies if env is None: env = Environment.build(self.build_builtin_environment(), self.build_user_environment()) ap_to_install = DependencyUtils.install(pilist, apmap, ipmap, env=env) # Check leaf min version min_version = check_leaf_min_version(ap_to_install) if min_version: raise LeafOutOfDateException( "You need to upgrade leaf to v{version} to install {text}". format(version=min_version, text=", ".join( [str(ap.identifier) for ap in ap_to_install]))) # Check nothing to do if len(ap_to_install) == 0: self.logger.print_default("All packages are installed") else: # Check available size download_totalsize = 0 download_count = 0 for ap in [ ap for ap in ap_to_install if isinstance(ap, AvailablePackage) ]: download_count += 1 if ap.size is not None: download_totalsize += ap.size fs_check_free_space(self.download_cache_folder, download_totalsize) # Confirm text = ", ".join([str(ap.identifier) for ap in ap_to_install]) self.logger.print_quiet( "Packages to install: {packages}".format(packages=text)) if download_totalsize > 0: self.logger.print_default("Total size:", sizeof_fmt(download_totalsize)) self.print_with_confirm(raise_on_decline=True) # Install prereq prereq_to_install = DependencyUtils.prereq( [ap.identifier for ap in ap_to_install], apmap, ipmap, env=env) if len(prereq_to_install) > 0: try: self.__install_prereq( prereq_to_install, ipmap, env=env, keep_folder_on_error=keep_folder_on_error) except BaseException as e: raise PrereqException(e) # Download ap list self.logger.print_default( "Downloading {size} package(s)".format( size=download_count)) la_to_install = [] for mf in ap_to_install: if isinstance(mf, AvailablePackage): la_to_install.append(self.__download_ap(mf)) elif isinstance(mf, LeafArtifact): la_to_install.append(mf) # Check the extracted size extracted_totalsize = 0 for la in la_to_install: if la.final_size is not None: extracted_totalsize += la.final_size else: extracted_totalsize += la.get_total_size() fs_check_free_space(self.install_folder, extracted_totalsize) # Extract la list for la in la_to_install: self.logger.print_default( "[{current}/{total}] Installing {la.identifier}". format(current=(len(out) + 1), total=len(la_to_install), la=la)) ip = self.__extract_artifact( la, env, ipmap, keep_folder_on_error=keep_folder_on_error) out.append(ip) return out
def execute(self, args, uargs): pm = PackageManager() env = None # If the user specified env values, build a complete env if args.custom_envlist is not None: env = Environment.build( pm.build_builtin_environment(), pm.build_user_environment(), Environment("Custom env", env_list_to_map(args.custom_envlist))) items = None if args.dependency_type == "available": items = DependencyUtils.install(PackageIdentifier.parse_list( args.packages), pm.list_available_packages(), {}, env=env) elif args.dependency_type == "install": items = DependencyUtils.install(PackageIdentifier.parse_list( args.packages), pm.list_available_packages(), pm.list_installed_packages(), env=env) elif args.dependency_type == "installed": items = DependencyUtils.installed(PackageIdentifier.parse_list( args.packages), pm.list_installed_packages(), env=env, ignore_unknown=True) elif args.dependency_type == "uninstall": items = DependencyUtils.uninstall(PackageIdentifier.parse_list( args.packages), pm.list_installed_packages(), env=env) elif args.dependency_type == "prereq": items = DependencyUtils.prereq(PackageIdentifier.parse_list( args.packages), pm.list_available_packages(), pm.list_installed_packages(), env=env) elif args.dependency_type == "upgrade": items, _ = DependencyUtils.upgrade( None if len(args.packages) == 0 else args.packages, pm.list_available_packages(), pm.list_installed_packages(), env=env) elif args.dependency_type == "rdepends": mfmap = OrderedDict() mfmap.update( DependencyUtils.rdepends(PackageIdentifier.parse_list( args.packages), pm.list_available_packages(), env=env)) mfmap.update( DependencyUtils.rdepends(PackageIdentifier.parse_list( args.packages), pm.list_installed_packages(), env=env)) items = mfmap.values() else: raise ValueError() rend = ManifestListRenderer() rend.extend(items) pm.print_renderer(rend)