def test_bootstrap_workspace(self): self.leaf_exec("init") self.leaf_exec(("profile", "create"), "foo") self.leaf_exec(("profile", "config"), "-p", "container-A") self.leaf_exec(("profile", "sync")) self.check_current_profile("foo") self.leaf_exec(("profile", "create"), "bar") self.check_current_profile("bar") self.leaf_exec("status") self.leaf_exec(("env", "print")) self.check_profile_content( "foo", ["container-A", "container-C", "container-D"]) data_folder = self.workspace_folder / LeafFiles.WS_DATA_FOLDERNAME self.assertTrue(data_folder.exists()) rmtree_force(data_folder) self.assertFalse(data_folder.exists()) self.leaf_exec("status") self.leaf_exec(("env", "print"), expected_rc=2) self.leaf_exec(("profile", "switch"), "foo") self.check_current_profile("foo") self.leaf_exec(("env", "print"), expected_rc=2) self.leaf_exec(("profile", "sync")) self.leaf_exec(("env", "print")) self.check_profile_content( "foo", ["container-A", "container-C", "container-D"])
def tearDown(self): # Reset env LeafSettings.VERBOSITY.value = None LeafSettings.CONFIG_FOLDER.value = None LeafSettings.CACHE_FOLDER.value = None LeafSettings.USER_PKG_FOLDER.value = None # Clean volatile folder rmtree_force(self.volatile_folder)
def __extract_artifact( self, la: LeafArtifact, env: Environment, install_folder: Path, ipmap: dict = None, keep_folder_on_error: bool = False) -> InstalledPackage: """ Install a leaf artifact @return InstalledPackage """ target_folder = install_folder / str(la.identifier) if target_folder.is_dir(): raise LeafException( "Folder already exists: {folder}".format(folder=target_folder)) # Check already installed ipmap = ipmap or self.list_installed_packages() if la.identifier in ipmap: raise LeafException( "Package is already installed: {la.identifier}".format(la=la)) # Check leaf min version min_version = check_leaf_min_version([la]) if min_version: raise LeafOutOfDateException( "You need to upgrade leaf to v{version} to install {la.identifier}" .format(version=min_version, la=la)) # Create folder target_folder.mkdir(parents=True) try: # Extract content self.logger.print_verbose("Extract {la.path} in {dest}".format( la=la, dest=target_folder)) with TarFile.open(str(la.path)) as tf: tf.extractall(str(target_folder)) # Execute post install steps out = InstalledPackage(target_folder / LeafFiles.MANIFEST) ipmap[out.identifier] = out self.__execute_steps(out.identifier, ipmap, StepExecutor.install, env=env) return out except Exception as e: self.logger.print_error("Error during installation:", e) if keep_folder_on_error: target_folder = mark_folder_as_ignored(target_folder) self.logger.print_verbose( "Mark folder as ignored: {folder}".format( folder=target_folder)) else: self.logger.print_verbose( "Remove folder: {folder}".format(folder=target_folder)) rmtree_force(target_folder) raise e
def setUp(self): if self.verbosity and LEAF_UT_SKIP.is_set(): if self.verbosity.lower() in LEAF_UT_SKIP.value.lower(): self.skipTest("Verbosity {verbosity} is ignored".format(verbosity=self.verbosity)) # Clean volatile folder just in case rmtree_force(self.volatile_folder) # Setup leaf via env LeafSettings.VERBOSITY.value = self.verbosity LeafSettings.CONFIG_FOLDER.value = self.config_folder LeafSettings.CACHE_FOLDER.value = self.cache_folder LeafSettings.USER_PKG_FOLDER.value = self.install_folder
def uninstall_packages(self, pilist: list): """ Remove given package """ with self.application_lock.acquire(): ipmap = self.list_installed_packages() iplist_to_remove = DependencyUtils.uninstall(pilist, ipmap, logger=self.logger) if len(iplist_to_remove) == 0: self.logger.print_default("No package to remove") else: # Confirm text = ", ".join( [str(ip.identifier) for ip in iplist_to_remove]) self.logger.print_quiet( "Packages to uninstall: {packages}".format(packages=text)) self.print_with_confirm(raise_on_decline=True) for ip in iplist_to_remove: if ip.read_only: raise LeafException( "Cannot uninstall system package {ip.identifier}". format(ip=ip)) self.logger.print_default( "Removing {ip.identifier}".format(ip=ip)) self.__execute_steps(ip.identifier, ipmap, StepExecutor.uninstall) self.logger.print_verbose( "Remove folder: {ip.folder}".format(ip=ip)) rmtree_force(ip.folder) del ipmap[ip.identifier] self.logger.print_default("{count} package(s) removed".format( count=len(iplist_to_remove)))
def tearDownClass(cls): # Do not remove folder in case of debug if not LEAF_UT_DEBUG.as_boolean(): rmtree_force(LeafTestCase._TEST_FOLDER)
return line def check_content(tester: TestCase, template_file: Path, lines: list, variables: dict): if template_file is None: # No check return if LEAF_UT_CREATE_TEMPLATE.as_boolean(): # Generate template if envar is set if not template_file.parent.exists(): template_file.parent.mkdir() with template_file.open("w") as fp: for line in lines: fp.write(replace_vars(line, variables, reverse=True) + "\n") # Check content with actual content template_lines = list( map(lambda l: replace_vars(l, variables, reverse=False), get_lines(template_file))) tester.assertEqual(lines, template_lines) if __name__ == "__main__": output = Path("/tmp/leaf/repository") print("Generate repository in {output}".format(output=output)) rmtree_force(output) mkdirs(output) generate_repository(TEST_REMOTE_PACKAGE_SOURCE, output)
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