def set(obj, key, value): """Store value against given key.""" api = lib.get_api(**obj) value = lib.parse(value, "json") lib.resilient_call( api.set_config, key, value, description=f"api.set_config({key}, <value>)" )
def logs(obj, plugins): """Print the latest install logs for given plugins.""" api = lib.get_api(**obj) # Despite the name, this only fetches the latest log for each plugin, not all! raw_info = lib.resilient_call( api.run_view, "pluginsmanager", "all_plugin_logs", description="api.run_view('pluginsmanager', 'all_plugin_logs')", idempotent=True, ) if plugins: # Filter to specified plugins. raw_info = [i for i in raw_info if i["name"] in plugins] for i in raw_info: for f in ( "name", "version", "description", "action", "server", "success", "when", ): lib.log(f"{f.capitalize()}: {i[f]}") lib.log("Logs:") if i["success"]: lib.log_output(i["output"].strip()) else: lib.log_error(i["output"].strip()) lib.log("") if len(raw_info) == 0 and len(plugins) > 0: lib.log( "No logs found. Note that any plugins must be exact name matches without version info." )
def make_from_encapsia(host: str) -> PluginInfos: # TODO: use pluginsmanager.plugins() if it exists api = lib.get_api(host=host) raw_info = lib.resilient_call( api.run_view, "pluginsmanager", "installed_plugins_with_tags", description= "api.run_view('pluginsmanager', 'installed_plugins_with_tags')", idempotent=True, ) pis = [] for i in raw_info: tags = i.get("plugin_tags") if not isinstance(tags, list): tags = [] try: variant = get_variant_from_tags(tags) except TooManyVariantTagsError as e: lib.log_error(f"Error in {i['name']} tag list: {e}") pi = PluginInfo.make_from_name_variant_version( i["name"], variant, i["version"]) pi.extras.update({ "description": i["description"], "installed": _format_datetime(i["when"]), "plugin-tags": ", ".join(sorted(tags)), }) pis.append(pi) return PluginInfos(pis)
def run_view(obj, namespace, function, args, post, upload, save_as): """Run a view in given plugin NAMESPACE and FUNCTION with ARGS. e.g. \b encapsia run view example_namespace test_view 3 tim limit=45 If an ARGS contains an "=" sign then send it as an optional query string argument. Otherwise send it as a URL path segment. """ api = lib.get_api(**obj) query_args = {} path_segments = [] for arg in args: if "=" in arg: left, right = arg.split("=", 1) query_args[left] = right else: path_segments.append(arg) result = lib.resilient_call( api.run_view, namespace, function, description=f"api.run_view({namespace}, {function})", view_arguments=path_segments, view_options=query_args, use_post=post, upload=upload, download=save_as, idempotent=not post, ) _log_result(result)
def get(obj, key): """Retrieve value against given key.""" api = lib.get_api(**obj) value = lib.resilient_call( api.get_config, key, description=f"api.get_config({key})", idempotent=True ) lib.pretty_print(value, "json")
def save(obj, output): """Save entire configuration to given file.""" api = lib.get_api(**obj) config = lib.resilient_call( api.get_all_config, description="api.get_all_config()", idempotent=True ) lib.pretty_print(config, "json", output=output)
def show(obj): """Show entire configuration.""" api = lib.get_api(**obj) config = lib.resilient_call( api.get_all_config, description="api.get_all_config()", idempotent=True ) lib.pretty_print(config, "json")
def _install_plugin(api, filename: Path, print_output: bool = False): """Use the API to install plugin directly from a file.""" if not filename.is_file(): lib.log_error(f"Cannot find plugin: {filename}", abort=True) blob_id = lib.resilient_call( api.upload_file_as_blob, filename.as_posix(), description=f"api.upload_file_as_blob({filename})", idempotent=True, # re-uploading a blob is safe ) lib.log(f"Uploaded {filename} to blob: {blob_id}") return lib.run_plugins_task( api, "install_plugin", dict(blob_id=blob_id), "Installing", print_output=print_output, idempotent=True, # re-installing a plugin should be safe )
def delete(obj, key): """Delete value against given key.""" api = lib.get_api(**obj) lib.resilient_call(api.delete_config, key, description=f"api.delete_config({key})")
def load(obj, input): """Load (merge) configuration from given file.""" api = lib.get_api(**obj) data = lib.parse(input.read(), "json") lib.resilient_call(api.set_config_multi, data, description="api.set_config_multi()")