Config Service
The Config Service provides a centralized persistent store for any configuration file used in the TMT Software System. All versions of configuration files are retained, providing a historical record of each configuration file. This client exposes simple methods to access and manage configuration files.
Rules and Checks
- The config file path must not contain
!#<>$%&'@^``~+,;=
or any whitespace character - If the input file is > 10MB or has lots of non ASCII characters, then for optimization, server will archive it in
annex
store. - Large and binary files can be forced to go to the
annex
store by usingannex=true
flag in create operation.
Model Classes
- ConfigData: Represents the contents of the files being managed. It wraps blob object.
- ConfigFileInfo: Represents information about a config file stored in the Config Service.
- ConfigFileRevision: Represents information about a specific version of a config file.
- ConfigId: Represents an identifier associated with a revision of a configuration file, often generated by create or update methods.
- ConfigMetadata: Represents metadata information about the Config Server.
- FileType: Represents the type of storage for a configuration file. Currently, two types are supported
Normal(small, text files)
andAnnex(Large, Binary files)
.
Example for creation ConfigData and accessing data with helper function
- Typescript
-
source
const dataArray = ['file-contents'] const configDataFromBlob: ConfigData = ConfigData.from(new Blob(dataArray)) const configDataFromFile: ConfigData = ConfigData.fromFile(new File(dataArray, 'filename')) const configDataFromString: ConfigData = ConfigData.fromString('someFileDataAsString') //accessing data const dataAsBlobContent: Blob = configDataFromString.toBlob() // notice use of async-await here. because this is an IO read call const readData = async (configData: ConfigData) => { const dataAsString: string = await configData.fileContentAsString() }
Note: Models other than ConfigData
are simple TypeScript classes and do not have special helper methods unlike ConfigData
.
Pre-requisite
In order to use config service
- The Location Service and Config Service Server needs to be running in the network
- The necessary configuration, environment variables or system properties should be defined to point to the correct host and port number(s) for the Location Service nodes.
- Authorization Token with correct access role. Documentation on how to fetch authorization token could be found here.
Creation of Config Service
To create a client for Config service
Config Service constructor takes TokenFactory
as an input argument.
- Typescript
-
source
const tokenFactory = () => auth.token const configService: ConfigService = await ConfigService(tokenFactory)
Note that the examples are using async/await which makes handling of promises more readable.
Usages of Config Service
Type Definitions of all methods can be found here
Creating File
This method takes path
at which configData
needs to be saved in the Config Service along with meta information i.e whether to be saved as annex
or normal
file and comment. After saving, it returns ConfigId
which can be used to access the saved file in the future using query methods.
Type definitions of create
method can be found here
- Typescript
-
source
const path = 'esw/sequencer/obsMode.conf' const comment = 'observation configuration on 21st november 2020' const author = 'OCS-Sequencer admin: Dave' const data = ` esw-sm { obsModes: { IRIS_Darknight: { resources: [IRIS, TCS, NFIRAOS] sequencers: [IRIS, ESW, TCS] }, IRIS_Cal: { resources: [IRIS, NSCU, NFIRAOS] sequencers: [IRIS, ESW, AOESW] }, WFOS_Cal: { resources: [WFOS] sequencers: [WFOS, ESW] } } } ` const configData = ConfigData.fromString(data) const sequencerConfigId: ConfigId = await configService.create(path, configData, false, comment)
Updating File
This method takes path
at which configData
needs to be updated in the Config Service along with comment. After updating, it returns ConfigId
which can be used to access the updated file in future using query methods.
Type definitions of update
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const commentOnUpdate = 'observation configuration on 23rd november 2020' const updatedData = ` esw-sm { obsModes: { IRIS_Darknight: { resources: [IRIS] sequencers: [IRIS] }, IRIS_Cal: { resources: [IRIS, NSCU, NFIRAOS] sequencers: [IRIS, ESW, AOESW] } } } ` const updatedConfigData = ConfigData.fromString(updatedData) const newSequencerConfigId: ConfigId = await configService.update(filePath, updatedConfigData, commentOnUpdate)
Fetching Files
The Config Service provides multiple ways to fetch a file from the svn repository based on Time
, ConfigId
,Active
, and Latest Revision
.
Following are the methods available to fetch files:
getActive
getById
getByTime
getLatest
Examples for each of the methods are as follows:
- getActive : This method return the
ConfigData
of the active version for that file if it exists otherwise returns undefined.
Type definitions of getActive
method can be found here
- Typescript
-
source
const file = 'esw/sequencer/obsMode.conf' const maybeActiveConfigData: Option<ConfigData> = await configService.getActive(file)
- getLatest : This method returns the
ConfigData
of the latest revision for that file if it exists otherwise returns undefined.
Type definitions of getLatest
method can be found here
- Typescript
-
source
const filepath = 'esw/sequencer/obsMode.conf' const maybeLatestConfigData: Option<ConfigData> = await configService.getLatest(filepath)
- getById : This method returns
ConfigData
based on the givenConfigId
if it exists otherwise returns undefined.
Type definitions of getById
method can be found here
- Typescript
-
source
const configId: ConfigId = await configService.update(filePath, updatedConfigData, commentOnUpdate) const maybeConfigData: Option<ConfigData> = await configService.getById(filepath, configId)
- getByTime : This method gets the
ConfigData
at the given path as it existed at a given time-instance.
Note: -If time-instance is before the file was created, the initial version is returned. -If time-instance is after the last change, the most recent version is returned.
Type definitions of getByTime
method can be found here
- Typescript
-
source
const configId1: ConfigId = await configService.create(filePath, updatedConfigData, false, commentOnUpdate) const beforeUpdate = new Date() const configId2: ConfigId = await configService.update(filePath, configData, commentOnUpdate) const afterUpdate = new Date() const maybeConfigData: Option<ConfigData> = await configService.getByTime(filepath, beforeUpdate) // maybeConfigData == updatedConfigData (i.e Initial revision of config) const newlyUpdatedData: Option<ConfigData> = await configService.getByTime(filepath, afterUpdate) // newlyUpdatedData == configData (i.e Latest revision of config)
Checking file existence
This method checks whether file exists at the given path
and optional specific configId
in the repository and returns true if it does exist or else false.
Type definitions of exists
method can be found here
- Typescript
-
source
const exists: boolean = await configService.exists(filePath) const exist: boolean = await configService.exists(filePath, configId)
Deleting File
This method deletes a file located at specified path
in the repository.
Type definitions of delete
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' await configService.delete(filePath, 'deleting the invalid config entry')
Listing files
This method list all the files for a given FileType
(Annex
or Normal
) and an optional pattern string, it will list all files with the file path matching the given pattern.
Some pattern examples are: “/path/hcd/*.*”
, “a/b/c/d.*”
, “.*.conf”
, “.*hcd.*”
Type definitions of list
method can be found here
- Typescript
-
source
const allAnnexFilesInfo: ConfigFileInfo[] = await configService.list({ type: 'Annex' }) const allNormalFilesInfo: ConfigFileInfo[] = await configService.list({ type: 'Normal' }) const allHcdAnnexFilesInfo: ConfigFileInfo[] = await configService.list({ type: 'Annex', pattern: '.*hcd.*' }) const allConfNormalFilesInfo: ConfigFileInfo[] = await configService.list({ type: 'Normal', pattern: '.*conf' })
Fetching revision history of a file
This method returns the history of revisions of the file at the given path
for a range of period specified by from
and to
.
The size of the list can be restricted using maxResults
.
Type definitions of history
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const from = new Date(2019, 12, 31) const to = new Date(2020, 12, 31) // upto 200 file revisions from 31st dec 2019 - 31st dec 2020 will be fetched const fileRevisions: ConfigFileRevision[] = await configService.history(filePath, from, to, 200)
Getting Config Service Metadata
This method returns metadata information about the Config Service. It includes:
- repository directory
- annex directory
- min annex file size
- max config file size
Type definitions of getMetadata
method can be found here
- Typescript
-
source
const metadata: ConfigMetadata = await configService.getMetadata()
Managing active versions
In its lifetime, a config file undergoes many revisions. An active version is a specific revision from a file’s history, and it is set by administrators.
historyActive
This method returns the history of active
revisions of the file at the given path
for a range of period specified by from
and to
. The size of the list can be restricted using maxResults
.
Type definitions of historyActive
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const from = new Date(2019, 12, 31) const to = new Date(2020, 12, 31) // upto 200 active file revisions from 31st dec 2019 - 31st dec 2020 will be fetched const activeFileRevisions: ConfigFileRevision[] = await configService.historyActive(filePath, from, to, 200)
setActiveVersion
This method sets the “active version” to be the version provided for the file at the given path. If this method is never called in a Config’s lifetime, the active version will always be the version returned by create function.
Type definitions of setActiveVersion
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const id: ConfigId = await configService.create(path, configData, false, comment) const commentWhileSetting = `Making ${id} active on 1st dec 2020` await configService.setActiveVersion(filePath, id, commentWhileSetting)
resetActiveVersion
This method resets the “active version” of the file at the given path to the latest version.
Type definitions of resetActiveVersion
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const id: ConfigId = await configService.create(path, configData, false, comment) const commentWhileResetting = `Making ${id} active version to latest as of 1st dec 2020` await configService.resetActiveVersion(filePath, commentWhileResetting)
getActiveVersion
This method returns the revision ID which represents the “active version” of the file at the given path.
Type definitions of getActiveVersion
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const maybeConfigId: Option<ConfigId> = await configService.getActiveVersion(filePath)
getActiveByTime
This method returns the content of active
version of the file existed at given instant of Time
Type definitions of getActiveByTime
method can be found here
- Typescript
-
source
const filePath = 'esw/sequencer/obsMode.conf' const at = new Date(2019, 12, 31) const maybeConfigData: Option<ConfigData> = await configService.getActiveByTime(filePath, at)