opensearch-project / OpenSearch-Dashboards

📊 Open source visualization dashboards for OpenSearch.
https://opensearch.org/docs/latest/dashboards/index/
Apache License 2.0
1.69k stars 894 forks source link

set custom config properties in opensearch_dashboards.yml, and access them from core/custom plugins #1353

Open DaCastle opened 2 years ago

DaCastle commented 2 years ago

Is your feature request related to a problem? Please describe.

Unable to set & access custom build-configuration properties.

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

I would like to be able to set & reference custom build-configuration properties from core/custom plugins.

Describe the solution you'd like

Be able to set custom config properties in opensearch_dashbaords.yml, and access them from core/custom plugins.

Additional context

OpenSearch Forum post tl;dr - I'm working on a fork of Dashboard, have logic added to the embeddable core plugin to parse/send received data to an external API, and currently have to hard code in the external api.

kavilla commented 2 years ago

Hello @DaCastle!

Thanks for opening! Could you provide an example? Like how you expect the configs to look like and how it is consumed by plugins?

DaCastle commented 2 years ago

Hey @kavilla !

The general idea would be to attach a list of key/value pairs in opensearch_dashboards.yml to the effect of:

opensearchDashboards.customVariables: [
  externalURL: 'url.here',
  companyBrandColor: 'string',
  anotherProperty: 'isCool'
]

And then importing to the effect of:

import { customVariables } from 'you/tell/me';

Whether the import can take place at any UI component level, or needs to be initialized in the plugin.tsx file of the desired plugin would be up for discussion as well.

This would allow us to add some functionality to a single forked branch, and simply update the config properties across our different external/internal use cases.

DaCastle commented 2 years ago

Well I found a work-around to accomplish this, although this still might be valuable to pursue in a new/better/proper/non-deprecated-function way.

Info

The opensearch_dashboard.yml --> opensearchDashboards.branding config object is already accessible to the UI code, but has some validation in place to prevent alteration.

steps

We will start at the top and work down, as it was the order I resolved this change in.

In opensearch_dashboards.yml, add your desired key/value at the bottom of the branding config area, like so:

opensearchDashboards.branding:
  logo:
    defaultUrl: ""
    darkModeUrl: ""
  mark:
    defaultUrl: ""
    darkModeUrl: ""
  loadingLogo: 
    defaultUrl: ""
    darkModeUrl: ""
  faviconUrl: ""
  applicationTitle: ""
  externalUrl: "google.com"

Then in opensearch_dashboards_config.ts, add you property & schema value to the bottom of the branding schema object:

applicationTitle: schema.string({
        defaultValue: '',
      }),
      externalUrl: schema.string({
        defaultValue: '',
      }),

Then onto rendering_service.tsx (src\core\server\rendering\rendering_service.tsx), adding to the bottom of the injectedMetadata branding object:

applicationTitle: brandingAssignment.applicationTitle,
externalUrl: brandingAssignment.externalUrl,

(you will see an error that the property does not exist on brandingAssignment yet (: )

Lower in the file where brandingAssignment is created & initialized:

applicationTitle,
externalUrl: branding.externalUrl,

(if you are inclined, you can add validation in the checkBrandingValid function is so desired)

In types.ts (src\core\server\rendering\types.ts), update the BrandingAssignment interface declaration:

applicationTitle?: string;
externalUrl?: string;

In custom_branding.ts (src\core\types\custom_branding.ts), update the Branding interface:

applicationTitle?: string;
externalUrl?: string;

Then the final piece to allow this to happen is in schema.js (src\legacy\server\config\schema.js), in the openSearchDashboards Joi.object definition:

applicationTitle: Joi.any().default(''),
externalUrl: Joi.any().default(''),

And then finally, finally, to get the branding object to be accessible at the plugin level, in a plugins' plugin.tsx file, you can access it via core.injectedMetadata.getBranding()

My current use case required me to alterations to the panel_header component, so to get it passed down via props, I altered the embeddable plugin.tsx (src\plugins\embeddable\public\plugin.tsx):

SavedObjectFinder={getSavedObjectFinder(core.savedObjects, core.uiSettings)}
branding={core.injectedMetadata.getBranding()}

I'm certainly still interested in your thoughts @kavilla !