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 Server State
Get information about the current in-memory state of all configured toggles. The response will give you transparency
about maintained values and the underlying configuration of the toggles. In the following example, the
/check/priority
toggle has a maintained root value, and two scoped values. All other toggles have no maintained
values, so they will use their fallback values.
Example Request/Response
- Request
GET /rest/feature/state Authorization: ...
- Response
HTTP/1.1 200 OK ...
{ "/check/priority": { "fallbackValue": 0, "rootValue": 1, "scopedValues": { "tenant::people": 10, "user::alice@wonderland.com": 100 }, "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" } } }
Read Redis State
Get information about the remote redis state of all toggles with maintained values, even ones that are not configured.
This endpoint will show the state within redis. Only toggles with maintained values will be shown here. In the example,
we can see /check/priority
with the maintained values. We can also see a /legacy-key
toggle, which has maintained
values that are not associated with a configuration { "SOURCE": "NONE" }
.
Note that reading the redis state can reveal legacy key values that used to be configured and maintained but are no
longer in the configuration. These values can be cleaned up by using the redisUpdate endpoint
with the remoteOnly
option.
Example Request/Responses
- Request
POST /rest/feature/redisRead Authorization: ...
- Response
HTTP/1.1 200 OK ...
{ "/check/priority": { "fallbackValue": 0, "rootValue": 1, "scopedValues": { "tenant::people": 10, "user::alice@wonderland.com": 100 }, "config": { "SOURCE": "FILE", "TYPE": "number", "VALIDATIONS": [ { "scopes": ["user", "tenant"] }, { "regex": "^\\d+$" }, { "module": "$CONFIG_DIR/validators", "call": "validateTenantScope" } ] } }, "/legacy-key": { "rootValue": 10, "scopedValues": { "tenant::a": 100, "tenant::b": 1000 }, "config": { "SOURCE": "NONE" } } }
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
Maintain a particular toggle value on Redis, which is automatically propagated 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 ...
- Valid Request with remoteOnly
POST /rest/feature/redisUpdate Authorization: ... Content-Type: application/json
{ "key": "/legacy-key", "value": null, "options": { "clearSubScopes": true, "remoteOnly": 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 } }
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-...", "..."]