def _fetch_repo_library( self, munki_repo, munki_repo_plugin, munkilib_dir, repo_subdirectory, force_munki_lib, ): if munki_repo_plugin == "FileRepo" and not force_munki_lib: return AutoPkgLib(munki_repo, repo_subdirectory) else: return MunkiLib(munki_repo, munki_repo_plugin, munkilib_dir, repo_subdirectory)
def main(self): library = self._fetch_repo_library( self.env["MUNKI_REPO"], self.env["MUNKI_REPO_PLUGIN"], self.env["MUNKILIB_DIR"], self.env.get("repo_subdirectory"), self.env["force_munki_repo_lib"], ) self.output(f"Using repo lib: {library.__class__.__name__}") self.output(f' plugin: {self.env["MUNKI_REPO_PLUGIN"]}') self.output(f' repo: {self.env["MUNKI_REPO"]}') # clear any pre-exising summary result if "munki_importer_summary_result" in self.env: del self.env["munki_importer_summary_result"] # Generate arguments for makepkginfo. args = ["/usr/local/munki/makepkginfo", self.env["pkg_path"]] if self.env.get("munkiimport_pkgname"): args.extend(["--pkgname", self.env["munkiimport_pkgname"]]) if self.env.get("munkiimport_appname"): args.extend(["--appname", self.env["munkiimport_appname"]]) # uninstaller pkg will be copied later, this is just to suppress # makepkginfo stderr warning output if self.env.get("uninstaller_pkg_path"): args.extend(["--uninstallpkg", self.env["uninstaller_pkg_path"]]) if self.env.get("additional_makepkginfo_options"): args.extend(self.env["additional_makepkginfo_options"]) # Call makepkginfo. try: proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=False) (out, err_out) = proc.communicate() except OSError as err: raise ProcessorError( f"makepkginfo execution failed with error code {err.errno}: " f"{err.strerror}") if err_out: for err_line in err_out.decode().splitlines(): self.output(err_line) if proc.returncode != 0: raise ProcessorError( f"creating pkginfo for {self.env['pkg_path']} failed: " f"{err_out.decode()}") # Get pkginfo from output plist. pkginfo = plistlib.loads(out) # copy any keys from pkginfo in self.env if "pkginfo" in self.env: for key in self.env["pkginfo"]: pkginfo[key] = self.env["pkginfo"][key] # copy any keys from metadata_additions if "metadata_additions" in self.env: pkginfo["_metadata"].update(self.env["metadata_additions"]) # set an alternate version_comparison_key # if pkginfo has an installs item if "installs" in pkginfo and self.env.get("version_comparison_key"): for item in pkginfo["installs"]: if not self.env["version_comparison_key"] in item: raise ProcessorError(( "version_comparison_key " f"'{self.env['version_comparison_key']}' could not be " f"found in the installs item for path '{item['path']}'" )) item["version_comparison_key"] = self.env[ "version_comparison_key"] # check to see if this item is already in the repo if self.env.get("force_munkiimport"): matchingitem = None else: matchingitem = self._find_matching_pkginfo(library, pkginfo) if matchingitem: self.env["pkginfo_repo_path"] = "" self.env["pkg_repo_path"] = os.path.join( self.env["MUNKI_REPO"], "pkgs", matchingitem["installer_item_location"]) self.env["munki_info"] = {} if "munki_repo_changed" not in self.env: self.env["munki_repo_changed"] = False self.output( f"Item {os.path.basename(self.env['pkg_path'])} already exists in the " f"munki repo as pkgs/{matchingitem['installer_item_location']}." ) return # import pkg install_path = library.copy_pkg_to_repo(pkginfo, self.env["pkg_path"]) pkginfo["installer_item_location"] = install_path.partition("pkgs/")[2] self.env["pkg_repo_path"] = install_path if self.env.get("uninstaller_pkg_path"): uninstall_path = library.copy_pkg_to_repo( pkginfo, self.env.get("uninstaller_pkg_path")) pkginfo["uninstaller_item_location"] = uninstall_path.partition( "pkgs/")[2] pkginfo["uninstallable"] = True # import icon icon_path = None if self.env.get("extract_icon"): # munki library is needed to extract and import icons if isinstance(library, MunkiLib): icon_library = library else: icon_library = MunkiLib( self.env["MUNKI_REPO"], self.env["MUNKI_REPO_PLUGIN"], self.env["MUNKILIB_DIR"], self.env.get("repo_subdirectory"), ) icon_path = icon_library.find_matching_icon(pkginfo) if not icon_path: icon_path = icon_library.extract_and_copy_icon_to_repo( self.env["pkg_path"], pkginfo, import_multiple=False) self.env["icon_repo_path"] = icon_path or "" # import pkginfo pkginfo_path = library.copy_pkginfo_to_repo( pkginfo, self.env.get("MUNKI_PKGINFO_FILE_EXTENSION", "plist")) self.env["pkginfo_repo_path"] = pkginfo_path # update env["pkg_path"] to match env["pkg_repo_path"] # this allows subsequent recipe steps to reuse the uploaded # pkg/dmg instead of re-uploading # This won't affect most recipes, since most have a single # MunkiImporter step (and it's usually the last step) self.env["pkg_path"] = self.env["pkg_repo_path"] self.env["munki_info"] = pkginfo self.env["munki_repo_changed"] = True self.env["munki_importer_summary_result"] = { "summary_text": "The following new items were imported into Munki:", "report_fields": [ "name", "version", "catalogs", "pkginfo_path", "pkg_repo_path", "icon_repo_path", ], "data": { "name": pkginfo["name"], "version": pkginfo["version"], "catalogs": ",".join(pkginfo["catalogs"]), "pkginfo_path": self.env["pkginfo_repo_path"].partition("pkgsinfo/")[2], "pkg_repo_path": self.env["pkg_repo_path"].partition("pkgs/")[2], "icon_repo_path": self.env["icon_repo_path"].partition("icons/")[2], }, } self.output(f'Copied pkginfo to: {self.env["pkginfo_repo_path"]}') self.output(f' pkg to: {self.env["pkg_repo_path"]}') if self.env.get("extract_icon"): self.output(f' icon to: {self.env["icon_repo_path"]}')