def get_all_bundles(): """ Returns a dictionary of name:object mappings """ bundles = {} if os.path.isdir(BUNDLE_ROOT): for name in os.listdir(BUNDLE_ROOT): try: bundle = get_bundle(get_bundle_root(name, absolute=True)) bundles[name] = bundle except FileNotFoundError as e: pass return bundles
def install_bundle(args): """ "Installs" a bundle (validates it and stores a copy). "Bundles" are just JSON problem unlock weightmaps which are exposed to and used by the web server. All problems specified in a bundle must already be installed. """ if not args.bundle_path: logger.error("No problem source path specified") raise FatalException bundle_path = args.bundle_path bundle_obj = get_bundle(bundle_path) if os.path.isdir(join(BUNDLE_ROOT, sanitize_name(bundle_obj["name"]))): logger.error( f"A bundle with name {bundle_obj['name']} is " + "already installed" ) raise FatalException for problem_name, info in bundle_obj["dependencies"].items(): if not os.path.isdir(join(PROBLEM_ROOT, problem_name)): logger.error( f"Problem {problem_name} must be installed " + "before installing bundle" ) raise FatalException for dependency_name in info["weightmap"]: if not os.path.isdir(join(PROBLEM_ROOT, dependency_name)): logger.error( f"Problem {dependency_name} must be installed " + "before installing bundle" ) raise FatalException bundle_destination = join( BUNDLE_ROOT, sanitize_name(bundle_obj["name"]), "bundle.json" ) os.makedirs(os.path.dirname(bundle_destination), exist_ok=True) shutil.copy(bundle_path, bundle_destination) logger.info(f"Installed bundle {bundle_obj['name']}")
def bundle_problems(args, config): """ Main entrypoint for generating problem bundles. """ bundle_path = args.bundle_path if os.path.isdir(args.bundle_path): bundle = get_bundle(args.bundle_path) bundle_path = join(args.bundle_path, "bundle.json") elif os.path.isfile(args.bundle_path): bundle = json.loads(open(args.bundle_path).read()) else: logger.error("No bundle could be found at '%s'", args.bundle_path) raise FatalException logger.debug("Starting to bundle: '%s'.", bundle["name"]) for problem_name in bundle["problems"]: installed_path = get_problem_root(problem_name, absolute=True) if not isdir(installed_path) or not get_problem(installed_path): logger.error("'%s' is not an installed problem.", problem_name) raise FatalException paths = {"working": getcwd() if args.out is None else args.out} if args.staging_dir: paths["staging"] = join(args.staging_dir, "__staging") else: paths["staging"] = join(paths["working"], "__staging") paths["debian"] = join(paths["staging"], "DEBIAN") paths["bundle_root"] = join(paths["staging"], get_bundle_root(bundle["name"])) [ makedirs(staging_path) for _, staging_path in paths.items() if not isdir(staging_path) ] # note that this chmod does not work correct if on a vagrant shared folder, # so we need to package the problems elsewhere chmod(dirname(paths["bundle_root"]), 0o750) bundle_to_control(bundle, paths["debian"]) copied_bundle_path = join(paths["bundle_root"], "bundle.json") copyfile(bundle_path, copied_bundle_path) def format_deb_file_name(bundle): """ Prepare the file name of the deb package according to deb policy. Args: bundle: the bundle object Returns: An acceptable file name for the bundle. """ raw_package_name = "{}-{}-bundle-{}.deb".format( sanitize_name(bundle.get("organization", "ctf")), sanitize_name(bundle["name"]), sanitize_name(bundle.get("version", "1.0-0"))) return raw_package_name deb_path = join(paths["working"], format_deb_file_name(bundle)) shell = spur.LocalShell() result = shell.run( ["fakeroot", "dpkg-deb", "--build", paths["staging"], deb_path]) if result.return_code != 0: logger.error("Error building bundle deb for '%s'.", bundle["name"]) logger.error(result.output) else: logger.info("Bundle '%s' packaged successfully.", bundle["name"]) logger.debug("Clearning up '%s' staging directory '%s'.", bundle["name"], paths["staging"]) rmtree(paths["staging"])
def bundle_problems(args, config): """ Main entrypoint for generating problem bundles. """ bundle_path = args.bundle_path if os.path.isdir(args.bundle_path): bundle = get_bundle(args.bundle_path) bundle_path = join(args.bundle_path, "bundle.json") elif os.path.isfile(args.bundle_path): bundle = json.loads(open(args.bundle_path).read()) else: raise Exception("No bundle {}".format(args.bundle_path)) for problem_name in bundle["problems"]: installed_path = get_problem_root(problem_name, absolute=True) if not isdir(installed_path) or not get_problem(installed_path): raise Exception("'{}' is not an installed problem.".format(problem_name)) paths = {"working": getcwd() if args.out is None else args.out} if args.staging_dir: paths["staging"] = join(args.staging_dir, "__staging") else: paths["staging"] = join(paths["working"], "__staging") paths["debian"] = join(paths["staging"], "DEBIAN") paths["bundle_root"] = join(paths["staging"], get_bundle_root(bundle["name"])) for _, staging_path in path.items(): if not isdir(staging_path): makedirs(staging_path) # note that this chmod does not work correct if on a vagrant shared folder, # so we need to package the problems elsewhere chmod(dirname(paths["bundle_root"]), 0o750) bundle_to_control(bundle, paths["debian"]) copied_bundle_path = join(paths["bundle_root"], "bundle.json") copyfile(bundle_path, copied_bundle_path) def format_deb_file_name(bundle): """ Prepare the file name of the deb package according to deb policy. Args: bundle: the bundle object Returns: An acceptable file name for the bundle. """ raw_package_name = "{}-{}-bundle-{}.deb".format( bundle.get("organization", "ctf"), bundle["name"], bundle.get("version", "1.0-0") ) return sanitize_name(raw_package_name) deb_path = join(paths["working"], format_deb_file_name(bundle)) shell = spur.LocalShell() result = shell.run(["fakeroot", "dpkg-deb", "--build", paths["staging"], deb_path]) if result.return_code != 0: print("Error building bundle deb for '{}'".format(bundle["name"])) print(result.output) else: print("Bundle '{}' packaged successfully.".format(bundle["name"])) print("Cleaning up staging directory '{}'.".format(paths["staging"])) rmtree(paths["staging"])