-
Notifications
You must be signed in to change notification settings - Fork 197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Vulnerabilities dashboard] Create the Dashboard
tab using OSD plugins
#5894
Comments
Dashboard
tab using opensearch plugins (Dashboard/Embeddables/Visualizations Builder) - More details belowDashboard
tab using opensearch plugins
Dashboard
tab using opensearch pluginsDashboard
tab using opensearch plugins
Dashboard
tab using opensearch pluginsDashboard
tab using OSD plugins
ProgressProgress has been made on the Dashboard tab within the vulnerability module. Visualizations have been implemented using the "renderer embeddable by value" feature of the OpenSearch Dashboards dashboard plugin. Below is a demo image illustrating the current state of the vulnerability module dashboard with example data. The search bar shown in the demo image, which is currently in place, will be replaced by the native search bar of OpenSearch Dashboard. This search bar effectively communicates with the visualizations on the dashboard. The data for these visualizations is sourced from the |
Analysis and solution of the bad request problemThe Embeddables' Container class plays a central role in configuring the different panels of the dashboard. This is where the final adjustments to inputs are made and they are added to the dashboard as panels one by one, rendering based on the corresponding factory obtained through the panel's "type" property. The "OnPanelAdded(panel: PanelState)" method of the Container class (extended by DashboardContainer) receives a "PanelState" object. From this object, the appropriate factory is extracted based on the type, and either "factory.createFromSavedObject" or "factory.create" is called depending on the presence of a "savedObjectId" in the input. In the specific case of using "DashboardContainerByValueRenderer" and given that the panel type is "visualization", the "create" method of "VisualizeEmbeddableFactory" is invoked. The "create(input: VisualizeInput & { savedVis?: SerializedVis }, parent?: IContainer)" method of the VisualizeEmbeddableFactory class takes the input processed by the Container and the parent object as parameters to create and return the embeddable of the corresponding type, in this case, a visualization. Being an embeddable by value, the "create" method calls "createVisEmbeddableFromObject(this.deps)" to create the embeddable using the input, an instance of Vis (created with the type and savedVis from the input), an array of savedVisualizations, attribute services, and the parent object. The return from "createVisEmbeddableFromObject" is an instance of VisualizeEmbeddable. However, a problem arises here. VisualizeEmbeddable has an "updateHandler" method to propagate detected changes. Additionally, when the "shouldFetchVisLayers" condition is met, it executes the "populateVisLayers" method, which makes a fetch request to obtain the "augmentVisSavedObjs", sometimes resulting in a 400 error as shown in the provided image. The critical point leading to a 400 error in the GET request occurs within the getAugmentVisSavedObjs function called by fetchVisLayers in the populateVisLayers process fetchVisLayers method code/**
* Collects any VisLayers from plugin expressions functions
* by fetching all AugmentVisSavedObjects that meets below criteria:
* - includes a reference to the vis saved object id
* - includes any of the plugin resource IDs, if specified
*/
fetchVisLayers = async (): Promise<VisLayers> => {
try {
const expressionParams: IExpressionLoaderParams = {
searchContext: {
timeRange: this.timeRange,
query: this.input.query,
filters: this.input.filters,
},
uiState: this.vis.uiState,
inspectorAdapters: this.inspectorAdapters,
};
const aborted = get(this.abortController, 'signal.aborted', false) as boolean;
const augmentVisSavedObjs = await getAugmentVisSavedObjs(
this.vis.id,
this.savedAugmentVisLoader,
undefined,
this.visAugmenterConfig?.visLayerResourceIds
);
if (!isEmpty(augmentVisSavedObjs) && !aborted && isEligibleForVisLayers(this.vis)) {
const visLayersPipeline = buildPipelineFromAugmentVisSavedObjs(augmentVisSavedObjs);
// The initial input for the pipeline will just be an empty arr of VisLayers. As plugin
// expression functions are ran, they will incrementally append their generated VisLayers to it.
const visLayersPipelineInput = {
type: 'vis_layers',
layers: [] as VisLayers,
};
// We cannot use this.handler in this case, since it does not support the run() cmd
// we need here. So, we consume the expressions service to run this directly instead.
const exprVisLayers = (await getExpressions().run(
visLayersPipeline,
visLayersPipelineInput,
expressionParams as Record<string, unknown>
)) as ExprVisLayers;
const visLayers = exprVisLayers.layers;
/**
* There may be some stale saved objs if any plugin resources have been deleted since last time
* data was fetched from them via the expression functions. Execute this trigger so any listening
* action can perform cleanup.
*
* TODO: this should be automatically handled by the saved objects plugin. Tracking issue:
* https://github.com/opensearch-project/OpenSearch-Dashboards/issues/4499
*/
getUiActions().getTrigger(PLUGIN_RESOURCE_DELETE_TRIGGER).exec({
savedObjs: augmentVisSavedObjs,
visLayers,
});
const err = getAnyErrors(visLayers, this.vis.title);
// This is only true when one or more VisLayers has an error
if (err !== undefined) {
const { toasts } = getNotifications();
toasts.addError(err, {
title: i18n.translate('visualizations.renderVisTitle', {
defaultMessage: `Error loading data on the ${this.vis.title} chart`,
}),
toastMessage: ' ',
id: this.id,
});
}
return visLayers;
}
} catch {
return [] as VisLayers;
}
return [] as VisLayers;
}; It's essential to specify at least one ID in the savedVis object within the visualization definition. Failure to do so will result in an error when generating a bad request, as the this.vis.id parameter received by getAugmentVisSavedObjs will lack the necessary value |
Description
Create the Dashboard tab using OSD plugins
Tasks
The text was updated successfully, but these errors were encountered: