Plugin and Service
- Plugin Settings
- Feature Vector Provider
- Service Endpoints for Read Privilege
- Service Endpoints for Write Privilege
- Service Endpoints for Admin Privilege
Plugin Settings
Here is a list of all plugin settings that can be used in package.json
under this library’s node cds.featureToggles
. All settings are optional.
setting | type | meaning |
---|---|---|
configFile | string | path of the configuration file |
config | object | inline configuration (only recommended for small projects) |
uniqueName | string | key name on redis, see below |
serviceAccessRoles | array | read and write access roles, see below |
readAccessRoles | array | see below |
writeAccessRoles | array | see below |
adminAccessRoles | array | see below |
ftsScopeCallback | string | custom scopes for cap feature toggles, see below |
uniqueName
The unique name is an identifier for the state data in redis. This defaults to the cloud foundry application name and usually need not be changed. Sometimes multiple apps want to access the same state though. In this case you would give all of them the same unique name. See single-key-approach for a diagram.
serviceAccessRoles, readAccessRoles, writeAccessRoles, adminAccessRoles
By default the FeatureService
read and write endpoints are accessible only to users with the CAP pseudo-role system-user. Different projects have their own access role preferences, so this setting allows them to set a list of strings, which represent the roles required to access the service. For details see @requires.
It will usually be sufficient to set the serviceAccessRoles
configuration, which covers both the read and write endpoints, but not the admin endpoints. If more discriminating access control is required, the readAccessRoles
and writeAccessRoles
can be set separately. For debugging purposes, you can also set the adminAccessRoles
.
As the name suggests, the adminAccessRoles
should be considered sensitive. It allows direct root access to the underlying redis.
ftsScopeCallback
First, read the Feature Vector Provider section for background. It may make sense to change the runtime scope for CAP Feature Toggles. For example, you might have a request header present that should be used as scope to distinguish toggle values. For this use-case:
- Create a file, e.g.,
srv/feature/ftsScope.js
:
/**
* @param context cds context
* @param key toggle key, to use different scopes for different toggles
*/
module.exports = (context, key) => {
const companyId; // your code here
return {
user: context?.user?.id,
tenant: context?.tenant,
companyId,
}
}
- Configure this file in
package.json
:
{
"cds": {
"featureToggles": {
"ftsScopeCallback": "./srv/feature/ftsScope.js"
}
}
}
Feature Vector Provider
When used as a CDS-Plugin, the library will automatically act as a Feature Vector Provider. This means feature toggles which match the /fts/<feature-name>
pattern and have a truthy current value at the start of a request will be passed to CDS, as they expect it, in req.features
.
In practice, if you have a CDS model extension feature in the directory <project>/fts/my-feature
, the library will automatically detect it and configure it as follows:
/fts/my-feature:
type: boolean
fallbackValue: false
This automatic configuration can be overwritten, by using a configuration file and adding a dedicated configuration with the same key /fts/my-feature
.
You can check and modify these feature toggles similarly to all others, and it will be provided to CDS and respected for the related requests. For an example check out the Example CAP Server.
Service Endpoints for Read Privilege
This service endpoint will enable operations teams to understand toggle states. For practical requests, check the http file in our example CAP Server.
Read Feature Toggles State
Get all information about the current in-memory state of all toggles.
Example Request/Response
- Request
GET /rest/feature/state Authorization: ...
- Response
HTTP/1.1 200 OK ...
{ "/check/priority": { "fallbackValue": 0, "config": { "SOURCE": "FILE", "TYPE": "number", "VALIDATIONS": [ { "scopes": ["user", "tenant"] }, { "regex": "^\\d+$" }, { "module": "$CONFIG_DIR/validators", "call": "validateTenantScope" } ] } }, "/memory/logInterval": { "fallbackValue": 0, "config": { "SOURCE": "FILE", "TYPE": "number", "VALIDATIONS": [ { "regex": "^\\d+$" } ] } }, "/fts/check-service-extension": { "fallbackValue": false, "config": { "SOURCE": "AUTO", "TYPE": "boolean" } } }
Service Endpoints for Write Privilege
Similar to the read privilege endpoints, these endpoints are meant to modify toggle state. For practical requests, check the http file in our example CAP Server.
Update Feature Toggle
Update the toggle state on Redis, which in turn is published to all server instances.
Example Request/Responses
- Valid Request
POST /rest/feature/redisUpdate Authorization: ... Content-Type: application/json
{ "key": "/check/priority", "value": 10, "scope": { "tenant": "people" } }
-
Response
HTTP/1.1 204 No Content ...
- Valid Request with clearSubScopes
POST /rest/feature/redisUpdate Authorization: ... Content-Type: application/json
{ "key": "/check/priority", "value": 10, "options": { "clearSubScopes": true } }
-
Response
HTTP/1.1 204 No Content ...
- Invalid Request
POST /rest/feature/redisUpdate Authorization: ... Content-Type: application/json
{ "key": "/check/priority", "value": "test" }
- Response
HTTP/1.1 422 Unprocessable Entity ...
{ "error": { "message": "value \"test\" has invalid type string, must be number", "code": "422", "@Common.numericSeverity": 4 } }
Re-Sync Server with Redis
Force server to re-sync with Redis, this should never be necessary. It returns the same JSON structure as /state
, after re-syncing.
Example Request/Response
- Request
POST /rest/feature/redisRead Authorization: ...
- Response
Same as Read Feature Toggles State.
Service Endpoints for Admin Privilege
The service also offers an additional endpoint for deep problem analysis.
Send Redis Command
Send an arbitrary command to Redis. https://redis.io/commands/
Example Request/Responses
- Request INFO
POST /rest/feature/redisSendCommand Authorization: ... Content-Type: application/json
{ "command": ["INFO"] }
- Response
HTTP/1.1 200 OK ...
# Server redis_version:4.0.10 redis_git_sha1:0 redis_git_dirty:0 redis_build_id:0 ...
- Request KEYS
POST /rest/feature/redisSendCommand Authorization: ... Content-Type: application/json
{ "command": ["KEYS", "features-*"] }
- Response
HTTP/1.1 200 OK ...
["features-...", "..."]