Skip to content

Commit 6c92d9c

Browse files
authored
Fb/service docs (#23)
* wip 1 * wip 2 * wip 3 * wip 4 * wip 5 * wip 6 * wip 7
1 parent dfe1fe0 commit 6c92d9c

File tree

5 files changed

+275
-53
lines changed

5 files changed

+275
-53
lines changed

docs/architecture/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
layout: default
33
title: Architecture
4-
nav_order: 3
4+
nav_order: 4
55
---
66

77
<!-- prettier-ignore-start -->

docs/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ npm install --save @cap-js-community/feature-toggle-library
2222
- feature toggle values can be changed specifically for accessors with certain scopes, e.g., for specific tenants, users,...
2323
- users can register change handler callbacks for specific toggles
2424
- users can register custom input validation callbacks for specific toggles
25+
- works as a [cds-plugin](https://cap.cloud.sap/docs/node.js/cds-plugins) and provides a REST service to read and manipulate toggles
2526

2627
## Further topics
2728

2829
- Configuration and code snippets: [Usage](usage)
30+
- REST service for CAP projects: [Service](service)
2931
- Architecture and related concepts: [Architecture](architecture)
3032
- Example CAP server: [CAP Example](https://github.com/cap-js-community/feature-toggle-library/blob/main/example-cap-server)

docs/service/index.md

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
---
2+
layout: default
3+
title: Service
4+
nav_order: 3
5+
---
6+
7+
<!-- prettier-ignore-start -->
8+
# Service
9+
{: .no_toc }
10+
<!-- prettier-ignore-end -->
11+
12+
<!-- prettier-ignore -->
13+
- TOC
14+
{: toc}
15+
16+
## CDS-Plugin Settings
17+
18+
Here is a list of all plugin settings that can be used in `package.json` under this library's node
19+
`cds.featureToggles`. At least one of _configFile_ or _config_ needs to be set, for the initialization to work.
20+
21+
| setting | type | meaning |
22+
| :----------------- | :----- | :------------------------------------------------------------------------ |
23+
| configFile | string | path of the [configuration]({{ site.baseurl }}/usage/#configuration) file |
24+
| config | object | inline configuration (only recommended for toy projects) |
25+
| serviceAccessRoles | array | see below |
26+
27+
_serviceAccessRoles_<br>
28+
Per default the service endpoints are accessible only to users with the CAP pseudo-role
29+
[system-user](https://cap.cloud.sap/docs/guides/authorization#pseudo-roles). Different projects have their own access
30+
role preferences, so this setting allows them to set a list of strings, which represent the roles required to access
31+
the service. For details see [@requires](https://cap.cloud.sap/docs/guides/authorization#requires).
32+
33+
## Service Endpoints
34+
35+
These service endpoints will enable operations teams to understand and modify toggle states. For practical requests,
36+
check the [http file](https://github.com/cap-js-community/feature-toggle-library/blob/main/example-cap-server/http/feature-service.http)
37+
in our example CAP Server.
38+
39+
### Read Server Memory State
40+
41+
Get all information about the current in-memory state of all toggles.
42+
43+
<b>Example Request/Response</b>
44+
45+
- Request
46+
```http
47+
GET /rest/feature/state
48+
Authorization: ...
49+
```
50+
- Response
51+
```
52+
HTTP/1.1 200 OK
53+
...
54+
```
55+
```json
56+
{
57+
"/check/priority": {
58+
"fallbackValue": 0,
59+
"config": {
60+
"TYPE": "number",
61+
"VALIDATION": "^\\d+$",
62+
"ALLOWED_SCOPES": ["user", "tenant"]
63+
}
64+
},
65+
"/memory/logInterval": {
66+
"fallbackValue": 0,
67+
"config": {
68+
"TYPE": "number",
69+
"VALIDATION": "^\\d+$"
70+
}
71+
}
72+
}
73+
```
74+
75+
---
76+
77+
### Update Toggle
78+
79+
Update the toggle state on Redis, which in turn is published to all server instances.
80+
81+
<b>Example Request/Responses</b>
82+
83+
- Valid Request
84+
```http
85+
POST /rest/feature/redisUpdate
86+
Authorization: ...
87+
Content-Type: application/json
88+
```
89+
```json
90+
{
91+
"key": "/check/priority",
92+
"value": 10,
93+
"scope": { "tenant": "people" }
94+
}
95+
```
96+
- Response
97+
98+
```
99+
HTTP/1.1 204 No Content
100+
...
101+
```
102+
103+
- Invalid Request
104+
```http
105+
POST /rest/feature/redisUpdate
106+
Authorization: ...
107+
Content-Type: application/json
108+
```
109+
```json
110+
{
111+
"key": "/check/priority",
112+
"value": "test"
113+
}
114+
```
115+
- Response
116+
```
117+
HTTP/1.1 422 Unprocessable Entity
118+
...
119+
```
120+
```json
121+
{
122+
"error": {
123+
"message": "value \"test\" has invalid type string, must be number",
124+
"code": "422",
125+
"@Common.numericSeverity": 4
126+
}
127+
}
128+
```
129+
130+
## Service Endpoints for Debugging
131+
132+
The service also offers additional endpoints to analyze problems.
133+
134+
### Re-Sync Server with Redis
135+
136+
Force server to re-sync with Redis, this should never be necessary. It returns the same JSON structure as
137+
`/state`, after re-syncing.
138+
139+
<b>Example Request/Response</b>
140+
141+
- Request
142+
```http
143+
POST /rest/feature/redisRead
144+
Authorization: ...
145+
```
146+
- Response<br>
147+
Same as [Read Server Memory State](#read-server-memory-state).
148+
149+
---
150+
151+
### Send Redis Command
152+
153+
Send an arbitrary command to Redis. [https://redis.io/commands/](https://redis.io/commands/)
154+
155+
<b>Example Request/Responses</b>
156+
157+
- Request INFO
158+
```http
159+
POST /rest/feature/redisSendCommand
160+
Authorization: ...
161+
Content-Type: application/json
162+
```
163+
```json
164+
{
165+
"command": ["INFO"]
166+
}
167+
```
168+
- Response
169+
```
170+
HTTP/1.1 200 OK
171+
...
172+
```
173+
```
174+
# Server
175+
redis_version:4.0.10
176+
redis_git_sha1:0
177+
redis_git_dirty:0
178+
redis_build_id:0
179+
...
180+
```
181+
- Request KEYS
182+
```http
183+
POST /rest/feature/redisSendCommand
184+
Authorization: ...
185+
Content-Type: application/json
186+
```
187+
```json
188+
{
189+
"command": ["KEYS", "features-*"]
190+
}
191+
```
192+
- Response
193+
```
194+
HTTP/1.1 200 OK
195+
...
196+
```
197+
```json
198+
["features-...", "..."]
199+
```

docs/usage/index.md

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,79 @@ back all toggles to their fallback values.
3838

3939
## Configuration
4040

41-
### Initialization
42-
4341
We recommend maintaining the configuration in a _version-tracked_, YAML- or JSON-file, which only changes during
44-
deployments. You will need to use the corresponding filepath, in order to initialize the feature toggles instance.
42+
deployments. The configuration is a key-value map describing each individual feature toggle. Here is an example in YAML.
43+
44+
```yaml
45+
/srv/util/logger/logLevel:
46+
type: string
47+
fallbackValue: info
48+
appUrl: \.cfapps\.sap\.hana\.ondemand\.com$
49+
validation: ^(?:error|warn|info|verbose|debug)$
50+
```
51+
52+
The semantics of these properties are as follows.
53+
54+
| property | required | meaning |
55+
| :------------ | :------- | :--------------------------------------------------------------- |
56+
| active | | if this is `false`, the corresponding feature toggle is inactive |
57+
| type | true | one of the allowed types `boolean`, `number`, `string` |
58+
| fallbackValue | true | see below |
59+
| appUrl | | see below |
60+
| validation | | regex for input validation |
61+
| allowedScopes | | see below |
62+
63+
_fallbackValue_<br>
64+
This value gets set initially when the feature toggle is introduced, and it is also used as a fallback when
65+
communication with Redis is interrupted during startup.
66+
67+
_appUrl_<br>
68+
Regex for activating feature toggle _only_ if the cf app's url matches
69+
70+
- for CANARY landscape `\.cfapps\.sap\.hana\.ondemand\.com$`
71+
- for EU10 landscape `\.cfapps\.eu10\.hana\.ondemand\.com$`
72+
- specific CANARY app `<cf-app-name>\.cfapps\.sap\.hana\.ondemand\.com$`
73+
74+
_allowedScopes_<br>
75+
This is an additional form of change validation. AllowedScopes can be set to a list of strings, for example
76+
`allowedScopes: [tenant, user]`. With this configuration only matching scopes can be used when setting feature toggle
77+
values.
78+
79+
{: .info }
80+
You can use the type `string` to encode more complex data types, like arrays or objects, but need to take care of the
81+
serialization/deserialization yourself. In these cases, make sure to use [external validation](#external-validation)
82+
so that new values can be deserialized correctly.
83+
84+
{: .warn }
85+
When using _active_ or _appUrl_ to block activation of a feature toggle, then user code accessing the
86+
feature toggle value will always get the fallback value.
87+
88+
## Initialization for CAP Projects
89+
90+
CAP projects, will use the library as a [cds-plugin](https://cap.cloud.sap/docs/node.js/cds-plugins). Their
91+
initialization settings are in `package.json`. For example:
92+
93+
```json
94+
{
95+
"cds": {
96+
"featureToggles": {
97+
"configFile": "./srv/feature/features.yaml"
98+
}
99+
}
100+
}
101+
```
102+
103+
In this example, the path `./srv/feature/feature.yaml` points to the previously discussed configuration file. With
104+
these settings in place, the `singleton` instance of the library will be initialized and is ready for usage at and
105+
after the [bootstrap](https://cap.cloud.sap/cap/docs/node.js/cds-server#bootstrap) event.
106+
107+
{: .info }
108+
Using the feature toggles in CAP projects also enables a [REST service]({{ site.baseurl }}/service/), where toggles can
109+
be read and manipulated.
110+
111+
## Initialization for Non-CAP Projects
112+
113+
Other projects will need to use the corresponding filepath, in order to initialize the feature toggles instance in code.
45114

46115
```javascript
47116
const pathlib = require("path");
@@ -93,54 +162,6 @@ const config = await readConfigFromFile(FEATURES_FILEPATH);
93162
await initializeFeatures({ config });
94163
```
95164

96-
### Format
97-
98-
The configuration is a key-value map describing each individual feature toggle. Here is an example in YAML.
99-
100-
```yaml
101-
/srv/util/logger/logLevel:
102-
type: string
103-
fallbackValue: info
104-
appUrl: \.cfapps\.sap\.hana\.ondemand\.com$
105-
validation: ^(?:error|warn|info|verbose|debug)$
106-
```
107-
108-
The semantics of these properties are as follows.
109-
110-
| property | required | meaning |
111-
| :------------ | :------- | :--------------------------------------------------------------- |
112-
| active | | if this is `false`, the corresponding feature toggle is inactive |
113-
| type | true | one of the allowed types `boolean`, `number`, `string` |
114-
| fallbackValue | true | see below |
115-
| appUrl | | see below |
116-
| validation | | regex for input validation |
117-
| allowedScopes | | see below |
118-
119-
_fallbackValue_<br>
120-
This value gets set initially when the feature toggle is introduced, and it is also used as a fallback when
121-
communication with Redis is blocked during startup.
122-
123-
_appUrl_<br>
124-
Regex for activating feature toggle _only_ if the cf app's url matches
125-
126-
- for CANARY landscape `\.cfapps\.sap\.hana\.ondemand\.com$`
127-
- for EU10 landscape `\.cfapps\.eu10\.hana\.ondemand\.com$`
128-
- specific CANARY app `<cf-app-name>\.cfapps\.sap\.hana\.ondemand\.com$`
129-
130-
_allowedScopes_<br>
131-
This is an additional form of change validation. AllowedScopes can be set to a list of strings, for example
132-
`allowedScopes: [tenant, user]`. With this configuration only matching scopes can be used when setting feature toggle
133-
values.
134-
135-
{: .info }
136-
You can use the type `string` to encode more complex data types, like arrays or objects, but need to take care of the
137-
serialization/deserialization yourself. In these cases, make sure to use [external validation](#external-validation)
138-
so that new values can be deserialized correctly.
139-
140-
{: .warn }
141-
When using active or appUrl to block activation of a feature toggle, then user code accessing the
142-
feature toggle value will _always_ get the fallback value.
143-
144165
## Environment Variables
145166

146167
The following environment variables can be used to fine-tune the library's behavior:

example-cap-server/http/feature-service.http

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
### state
1+
### read state
22
GET {{base_url}}/rest/feature/state
33
Authorization: Basic system system
44

0 commit comments

Comments
 (0)