@mojaloop/platform-configuration-bc-client-lib
v0.6.3
Published
Mojaloop platform configuration client lib
Downloads
41
Keywords
Readme
Mojaloop vNext Platform Configuration Client Library
This library provides a nodejs platform configuration client implementation, to be used by components that require centrally stored and managed configurations. It works in conjunction with the platform configuration central service (check the see also section below).
There are two sets of configurations:
- Per bounded context configurations - with schemas defined by the bounded contexts
- Global configurations - with schemas defined centrally by the Platform Configuration BC code and its config bootstrapper
Usage (quick start)
Create the configuration schema
"use strict"
import {ConsoleLogger} from "@mojaloop/logging-bc-public-types-lib";
import {ConfigParameterTypes} from "@mojaloop/platform-configuration-bc-public-types-lib";
import {IConfigProvider, ConfigurationClient, DefaultConfigProvider} from "@mojaloop/platform-configuration-bc-client-lib";
const BC_NAME = "my-bounded-context"; // Bounded context registering the configuration schema
const APP_NAME = "my-server-app"; // Application name using the ConfigurationClient
const APP_VERSION = "0.1.2"; // Version of the application (should come from npm env var)
const SCHEMA_VERSION = "0.0.1"; // This is the version of the config schema
const CONFIG_SVC_BASEURL = "http://localhost:3100"; // Base URL of the configuration REST service
const AUTH_TOKEN_ENPOINT = "http://localhost:3201/token"; // Token endpoint of the authentitcation REST service
// Service credentials of the Application using the ConfigurationClient (provisioned from authentitcation-svc)
const CLIENT_ID = "my-server-app";
const CLIENT_SECRET = "superServiceSecret";
const logger = new ConsoleLogger();
// mandatory - create an instance of IAuthenticatedHttpRequester
const authRequester = new AuthenticatedHttpRequester(logger, AUTH_TOKEN_ENPOINT);
authRequester.setAppCredentials(CLIENT_ID, CLIENT_SECRET);
// optional - messageConsumer required to enable automatic reloads, triggered by server changes
const messageConsumer = new MLKafkaJsonConsumer({kafkaBrokerList: "localhost:9092", kafkaGroupId: "test"}, logger);
// create the default provider instance
const defaultConfigProvider:IConfigProvider = new DefaultConfigProvider(logger, authRequester, messageConsumer, CONFIG_SVC_BASEURL);
// NOTE: you can skip passing the CONFIG_SVC_BASEURL to the DefaultConfigProvider constructor (or pass null)
// if the PLATFORM_CONFIG_BASE_SVC_URL env var contains the platform config service base url
// const defaultConfigProvider:IConfigProvider = new DefaultConfigProvider();
// create the configClient instance, passing the defaultConfigProvider
const configClient = new ConfigurationClient(BC_NAME, APP_NAME, APP_VERSION, CONFIGSET_VERSION, defaultConfigProvider);
// Add the parameters your Bounded Context uses to the configuration schema
configClient.bcConfigs.addNewParam("stringParam1", ConfigParameterTypes.STRING, "default val", "description string param 1");
configClient.bcConfigs.addNewParam("boolParam1", ConfigParameterTypes.BOOL, true, "description bool param 1");
configClient.bcConfigs.addNewParam("intParam1", ConfigParameterTypes.INT_NUMBER, 42, "description int number param 1");
configClient.bcConfigs.addNewParam("floatParam1", ConfigParameterTypes.FLOAT_NUMBER, 3.1415, "description float number param 1");
// Add object param, including JSON Type Definition (JTD) which can be used with OBJECT and LIST param types
// JTD will be used to validate future value changes, specification here: https://datatracker.ietf.org/doc/rfc8927/
// Note: For ConfigParameterTypes.LIST, the JTD is the specification for each item, not the entire array
configClient.bcConfigs.addNewParam(
"objParam1",
ConfigParameterTypes.OBJECT,
{name: "Pedro", age: 46},
"description",
'{"properties":{"name":{"type":"string"},"age":{"type":"int32"}}}'
);
// Add the feature flags your Bounded Context uses to the configuration schema
configClient.bcConfigs.addNewFeatureFlag("useBetaFeatureY", false, "description feature flag");
// Add the secrets your Bounded Context uses to the configuration schema
configClient.bcConfigs.addNewSecret("secret1", "password", "description secret 1");
Initialise the client
(continued from code snippet above)
await configClient.init();
Bootstrap - send the configuration schema to the central service
(continued from code snippet above)
const bootStrapSuccess = await configClient.bootstrap();
Fetch the current values from the central service
This will get both the Bounded Context config schema current values and the global schema current values.
(continued from code snippet above)
await configClient.fetch();
Hook the change notification mechanism (must instantiate the provider with a messageConsumer)
(continued from code snippet above)
configClient.setChangeHandlerFunction((type:"BC"|"GLOBAL") => {
console.log("Configurations where changed in the service and have been re-fetched already");
if(type==="BC")
console.log(" Changes were on this bounded context configuration set");
else
console.log(" Changes were on the global configuration set");
});
After init() and fetch() you can use your configClient instance anywhere you need config values
Get your own Bounded Context schema values - current version and latest iteration
const stringParam1Obj = configClient.bcConfigs.getParam("stringParam1");
const stringParam1: string = stringParam1Obj.currentValue;
const boolParam1Obj = configClient.bcConfigs.getParam("boolParam1");
const boolParam1: boolean = boolParam1Obj.currentValue;
const intParam1Obj = configClient.bcConfigs.getParam("intParam1");
const intParam1: number = intParam1Obj.currentValue;
const floatParam1Obj = configClient.bcConfigs.getParam("floatParam1");
const floatParam1: number = floatParam1Obj.currentValue;
const featureFlag1Obj = configClient.bcConfigs.getFeatureFlag("featureFlag1");
const featureFlag1: boolean = featureFlag1Obj.currentValue;
const secret1Obj = configClient.bcConfigs.getSecret("secret1");
const secret1: string = secret1Obj.currentValue;
Global schema values - latest version and iteration
const globalParam1Obj = configClient.globalConfigs.getParam("globalParam1");
const strGlobalParam1: string = globalParam1Obj.currentValue;
const globalFeatureFlag1Obj = configClient.globalConfigs.getFeatureFlag("globalFeatureFlag1");
const globalFeatureFlag1: boolean = globalFeatureFlag1Obj.currentValue;
const globalSecret1Obj = configClient.globalConfigs.getSecret("globalSecret1");
const globalSecret1: string = globalSecret1Obj.currentValue;
Note: The getParam
, getFeatureFlag
and getSecret
will return null if the config items are not found
You can also request all params, feature flags and secrets, using the getAllParams
, getAllFeatureFlags
and getAllSecrets
, respectively.
Reacting to platform configuration changes triggered upstream
See example above on how to use ConfigurationClient.setChangeHandlerFunction()
How it works
- Bounded contexts define a configuration schema, which include the configurations items they need the configuration schema version;
- This configuration schema is sent to the central service by the client during the boostrap step, and stored in the form of a
ConfigurationSet
list; - Administrators can change the central values (and trigger change notifications to connected clients);
- Everytime a change is made in a configuration set, its
iterationNumber
increases by one; - Applications can fetch the centrally stored values at startup, on time, or as result of centrally emitted change notification.
In a configuration schema, there are three types of configuration values:
- Parameters - General parameters that can be of type: bool, string, int and float
- Feature Flags - These are boolean values, which can be enabled or disabled
- Secrets - Centrally stored string secret values
All per bc configuration schemas are identified by their owner bounded context. All configuration types have a unique name and a description. Parameters and Feature Flags have a default value that is provided by the developer (secrets, for security reasons do not have te ability to set a default value).
The per bounded context configuration schema that is sent to the central service by the client during the boostrap step, called BoundedContextConfigurationSet
, looks like:
export type BoundedContextConfigurationSet = {
boundedContextName: string; // target bounded context
schemaVersion: string; // schema version (semver format)
iterationNumber: number; // monotonic integer - increases on every configuration/values change
readonly parameters: ConfigParameter[]; // parameter list
readonly featureFlags: ConfigFeatureFlag[]; // featureFlag list
readonly secrets: ConfigSecret[]; // secret list
}
This client library provides an ConfigurationClient
object that encapsulates both the BoundedContextConfigurationSet
and the GlobalConfigurationSet
, which deliver all the functionality required by the consuming Bounded Context.
The ConfigurationClient
requires an implementation of a IConfigProvider
in order to interact with the central/remote system. The library provides a default implementation that allows the client to connect to the default central system interface.
For development only purposes, the client can be instantiated without an IConfigProvider
implementation - this forces the client to work in a standalone mode, using only locally provided values.
Load order / precedence
- Parameter / FeatureFlag / ~~Secret~~ default values definition when instantiating the
ConfigurationClient
; - Fetch request (from the IConfigProvider) that fetches central/remote values;
- Environment Variables - these can be defined at OS level before the application starts.
Note: Each step overrides the previous
DefaultProvider configuration via env var
The default implementation of the ConfigProvider
this library provides, called DefaultConfigProvider
can be configured via an environment variable, to that end, set the PLATFORM_CONFIG_BASE_SVC_URL
env var with the value of the central platform configuration service base url and construct the DefaultConfigProvider
instance without passing a configSvcBaseUrl
.
Overriding with Environment Variables
All configuration values can be overridden locally by defining a configuration value with the following name format:
- For local per bounded context config items:
ML_BC_
+CONFIG_ITEM_NAME_UPPERCASE
- For global config items:
ML_GLOBAL_
+CONFIG_ITEM_NAME_UPPERCASE
Example
For the following parameter:
configClient.addNewParam(
"serverBaseUrl",
ConfigParameterTypes.STRING,
"http://localhost:3000",
"Base URL for the server, including protocol and port"
);
Set the environment variable with corresponding name to override the parameter:
export ML_BC_SERVERBASEURL=https://192.168.1.1:443
Standalone mode (for development)
Standalone mode means that no values will be fetched from the central/remote service. In other works, any provided IConfigProvider
will be disabled.
This might be useful in local development mode, where the central service is not available.
There are two ways to have the ConfigurationClient working in standalone:
- By setting a specially called env var with any non-null value, called:
PLATFORM_CONFIG_STANDALONE
- By providing a null
IConfigProvider
when instantiating theConfigurationClient
object.
Bootstrapping initial / new configuration schemas
See also
This client is aligned with the central component of the Mojaloop vNex Platform Configuration.
- See the
@mojaloop/platform-configuration-bc-types-lib
library here for the shared types. - See the central configuration service here
Install
To install this library use:
npm install @mojaloop/platform-configuration-bc-client-lib
OR
yarn add @mojaloop/platform-configuration-bc-client-lib