def _generate_rows(self, args, kwargs): # instantiate the plugin with arguments. self.plugin_obj = self.plugin_cls(session=self.session, *args, **kwargs) output_header = getattr(self.plugin_cls, "table_header", None) collector = getattr(self.plugin_obj, "collect_as_dicts", None) if callable(collector) and output_header is not None: # The plugin supports the collect API and declares its output ahead # of time. This is the ideal case. self.columns = output_header return repeated.lazy( lambda: self._order_columns(output_header, collector)) else: # TODO: Should we not support these kind of plugins? # We don't know enough about the plugin to do the easy thing. We # need to create a shim renderer that will cache the plugin output # and then use that. renderer = identity_renderer.IdentityRenderer(session=self.session) with renderer.start(): self.session.RunPlugin(self.plugin_cls.name, format=renderer, *args, **kwargs) # The identity renderer will now contain the plugin output and # columns. self.columns = renderer.columns return repeated.repeated(*list(renderer.rows))
def _select_plugin(self, key): """Get output from a plugin indicated by key. This has two modes of operation. If the plugin is typed we can just run collect. If it doesn't, we pass the render function a special renderer which preserves output. The renderer instances we pass the plugins also preserve the table headers and are cached in _cached_plugin_renderers for future reference. Returns: An instance of IdentityRenderer holding table header and rows. """ meta = self.session.plugins.plugin_db.GetActivePlugin(key) plugin_cls = meta.plugin_cls # The identity renderer will contain all the rendered rows. renderer = identity_renderer.IdentityRenderer() self._cached_plugin_renderers[key] = renderer if issubclass(plugin_cls, plugin.TypedProfileCommand): # We have access to table_header and rows without running render. renderer.table_header = plugin_cls.table_header plugin_curry = getattr(self.session.plugins, key) renderer.rows = list(plugin_curry().collect_as_dicts()) else: # We have to run the plugin to get output. self.session.RunPlugin(key, format=renderer) return renderer
def apply(self, args, kwargs): """Instantiate the plugin with given args and run it. This caches the output of the plugin. Subsequently, table_header, rows and columns will be populated. The CommmandWrapper must not be applied twice with different arguments - each instance represents a unique application. Arguments: args, kwargs: Arguments to the plugin. """ if self._applied_args is not None: # Called before. Return what we cached. if self._applied_args != (args, kwargs): raise ValueError( "%r was previously called with %r but is now being called" " with %r. This should never happen." % (self, self._applied_args, (args, kwargs))) return self.rows kwargs = kwargs.copy() kwargs.pop("vars", None) self._applied_args = (args, kwargs) # First time - instantiate the plugin with arguments. plugin_curry = getattr(self.session.plugins, self.plugin_cls.name) self.plugin_obj = plugin_curry(session=self.session, *args, **kwargs) output_header = getattr(self.plugin_cls, "table_header", None) collector = getattr(self.plugin_obj, "collect_as_dicts", None) if callable(collector) and output_header is not None: # The plugin supports the collect API and declares its output ahead # of time. This is the ideal case. self.columns = output_header self.rows = repeated.lazy(collector) else: # We don't know enough about the plugin to do the easy thing. We # need to create a shim renderer that will cache the plugin output # and then use that. renderer = identity_renderer.IdentityRenderer(session=self.session) with renderer.start(): self.session.RunPlugin(self.plugin_cls.name, format=renderer, *args, **kwargs) # The identity renderer will now contain the plugin output and # columns. self.columns = renderer.columns self.rows = repeated.repeated(*list(renderer.rows)) return self.rows
def apply(self, args, kwargs): """Instantiate the plugin with given args and run it. Note: Apply will only run once per instance - once we have rows it will not rerun, even if the arguments change! Arguments: args, kwargs: Arguments to the plugin. """ if self._applied_args is None: self._applied_args = (args, kwargs) else: if self._applied_args != (args, kwargs): raise ValueError("%r was previously called with %r but is now " "being called with %r." % (self, self._applied_args, (args, kwargs))) else: # Results already cached. return self if issubclass(self.plugin_cls, plugin.TypedProfileCommand): # We have access to table header and rows without running render. self.table_header = self.plugin_cls.table_header plugin_curry = getattr(self.session.plugins, self.plugin_cls.name) command = plugin_curry(session=self.session, *args, **kwargs) self.rows = list(command.collect_as_dicts()) self.columns = self.table_header.header else: # We do not have a table header declaration, so we need to run # the plugin and use an identity renderer to capture its output # and headers. # The identity renderer will capture rendered rows. renderer = identity_renderer.IdentityRenderer() self.session.RunPlugin(self.plugin_cls.name, format=renderer, *args, **kwargs) self.rows = renderer.rows self.columns = renderer.columns return self