Skip to content

Commit

Permalink
Improve dynamic config
Browse files Browse the repository at this point in the history
Signed-off-by: Tianle Huang <tianleh@amazon.com>
  • Loading branch information
tianleh committed Apr 11, 2024
1 parent 7e1d940 commit 5402d15
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 9 deletions.
4 changes: 2 additions & 2 deletions config/opensearch_dashboards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
# opensearchDashboards.configIndex: ".opensearch_dashboards_config"

# Set the value of this setting to true to enable plugin application config. By default it is disabled.
# application_config.enabled: false
application_config.enabled: true

# Set the value of this setting to true to enable plugin CSP handler. By default it is disabled.
# It requires the application config plugin as its dependency.
# csp_handler.enabled: false
csp_handler.enabled: true

# The default application to load.
#opensearchDashboards.defaultAppId: "home"
Expand Down
26 changes: 23 additions & 3 deletions src/plugins/application_config/server/opensearch_config_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,57 @@
* SPDX-License-Identifier: Apache-2.0
*/

import LRUCache from 'lru-cache';
import { IScopedClusterClient, Logger } from '../../../../src/core/server';

import { ConfigurationClient } from './types';
import { validate } from './string_utils';

export class OpenSearchConfigurationClient implements ConfigurationClient {
private client: IScopedClusterClient;
private configurationIndexName: string;
private readonly logger: Logger;
private cache: LRUCache<string, string>;

constructor(
scopedClusterClient: IScopedClusterClient,
configurationIndexName: string,
logger: Logger
logger: Logger,
cache: LRUCache<string, string>
) {
this.client = scopedClusterClient;
this.configurationIndexName = configurationIndexName;
this.logger = logger;
this.cache = cache;
}

async getEntityConfig(entity: string) {
const entityValidated = validate(entity, this.logger);

const cachedValue = this.cache.get(entityValidated);

if (this.cache.has(entityValidated)) {
this.logger.info(`found value ${cachedValue} from cache`);
return cachedValue;
}

this.logger.info('No value found in cache');

try {
const data = await this.client.asInternalUser.get({
index: this.configurationIndexName,
id: entityValidated,
});
const value = data?.body?._source?.value || '';

this.cache.set(entityValidated, value);

return data?.body?._source?.value || '';
return value;
} catch (e) {
const errorMessage = `Failed to get entity ${entityValidated} due to error ${e}`;

this.logger.error(errorMessage);

this.cache.set(entityValidated, '');
throw e;
}
}
Expand All @@ -55,6 +71,8 @@ export class OpenSearchConfigurationClient implements ConfigurationClient {
},
});

this.cache.set(entityValidated, newValueValidated);

return newValueValidated;
} catch (e) {
const errorMessage = `Failed to update entity ${entityValidated} with newValue ${newValueValidated} due to error ${e}`;
Expand All @@ -74,6 +92,8 @@ export class OpenSearchConfigurationClient implements ConfigurationClient {
id: entityValidated,
});

this.cache.del(entityValidated);

return entityValidated;
} catch (e) {
if (e?.body?.error?.type === 'index_not_found_exception') {
Expand Down
21 changes: 18 additions & 3 deletions src/plugins/application_config/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Observable } from 'rxjs';
import { first } from 'rxjs/operators';

import LRUCache from 'lru-cache';
import {
PluginInitializerContext,
CoreSetup,
Expand All @@ -14,6 +15,8 @@ import {
Logger,
IScopedClusterClient,
SharedGlobalConfig,
OpenSearchDashboardsRequest,
IClusterClient,
} from '../../../core/server';

import {
Expand All @@ -31,11 +34,20 @@ export class ApplicationConfigPlugin

private configurationClient: ConfigurationClient;
private configurationIndexName: string;
private clusterClient: IClusterClient;

private cache: LRUCache<string, string>;

constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
this.config$ = initializerContext.config.legacy.globalConfig$;
this.configurationIndexName = '';
this.clusterClient = null;

this.cache = new LRUCache({
max: 30,
maxAge: 100 * 1000,
});
}

private registerConfigurationClient(configurationClient: ConfigurationClient) {
Expand All @@ -50,15 +62,16 @@ export class ApplicationConfigPlugin
this.configurationClient = configurationClient;
}

private getConfigurationClient(scopedClusterClient: IScopedClusterClient): ConfigurationClient {
private getConfigurationClient(request: OpenSearchDashboardsRequest): ConfigurationClient {
if (this.configurationClient) {
return this.configurationClient;
}

const openSearchConfigurationClient = new OpenSearchConfigurationClient(
scopedClusterClient,
this.clusterClient.asScoped(request),
this.configurationIndexName,
this.logger
this.logger,
this.cache
);

return openSearchConfigurationClient;
Expand All @@ -81,6 +94,8 @@ export class ApplicationConfigPlugin
}

public start(core: CoreStart) {
this.clusterClient = core.opensearch.client;

return {};
}

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/csp_handler/server/csp_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function createCspRulesPreResponseHandler(

const [coreStart] = await core.getStartServices();

const client = getConfigurationClient(coreStart.opensearch.client.asScoped(request));
const client = getConfigurationClient(request);

const cspRules = await client.getEntityConfig(CSP_RULES_CONFIG_KEY, {
headers: request.headers,
Expand Down

0 comments on commit 5402d15

Please sign in to comment.