Skip to content

Commit 8da5783

Browse files
committed
feat(api): add support for flag env migration
makes it possible to copy flag setting such as targeting between environments, and cleans up error handing. plus removal of old 'api.js' in favour of 'ldutils' executable. BREAKING CHANGE: removed support for 'api' js
1 parent 81459e4 commit 8da5783

File tree

6 files changed

+154
-247
lines changed

6 files changed

+154
-247
lines changed

README.md

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,10 @@ Please note that the api token is not the same as your sdk keys. You need to ge
2727

2828
### commandline usage OLD
2929
This command line support was primarily for debugging api calls. The NEW version below is aimed at general usage.
30-
```
31-
export LAUNCHDARKLY_API_TOKEN=<api-token>
32-
33-
// collect all flags for a project
34-
npm run api -- getFeatureFlags <myProjectId>
3530

36-
// update or create a customRole with array of policies
37-
npm run api -- upsertCustomRole <customRoleKey> <customRoleName> '[{"resources":["proj/*"],"actions":["*"],"effect":"allow"}]'
38-
```
3931

40-
### commandline usage NEW (in progress)
41-
A more complete commandline solution is underway - try it out using:
32+
### commandline usage
33+
After cloning this repo you can make `ldutils` executable, and use it to make api calls based on passed in parameters.
4234

4335
```
4436
chmod 755 ./ldutils
@@ -47,7 +39,30 @@ chmod 755 ./ldutils
4739

4840
The above will display a help screen of instructions, thanks to https://github.com/tj/commander.js/
4941

50-
Make sure you have env var LAUNCHDARKLY_API_TOKEN set, and if piping output to another command, ensure that LAUNCHDARKLY_API_LOGLEVEL is not set to 'debug'.
42+
Optionally you can add `ldutils` to your PATH:
43+
44+
```
45+
# cloned repo
46+
sudo ln -s /<clonepath>/launchdarkly-nodeutils/ldutils /usr/local/bin/ldutils
47+
48+
# or after 'npm install launchdarkly-nodeutils --save'
49+
sudo ln -s /<installpath>/node_modules/launchdarkly-nodeutils/ldutils /usr/local/bin/ldutils
50+
51+
52+
```
53+
54+
> Make sure you have env var LAUNCHDARKLY_API_TOKEN set, and if piping output to another command, ensure that LAUNCHDARKLY_API_LOGLEVEL is not set to 'debug' to ensure only the json result of the command is returned.
55+
56+
Here are some examples of commandline usage (if you have not added ldutils to PATH, prefix with `./`:
57+
```
58+
export LAUNCHDARKLY_API_TOKEN=<api-token>
59+
60+
// collect all flags for a project
61+
ldutils getFeatureFlags <myProjectId>
62+
63+
// update or create a customRole with array of policies
64+
ldutils upsertCustomRole <customRoleKey> <customRoleName> '[{"resources":["proj/*"],"actions":["*"],"effect":"allow"}]'
65+
```
5166

5267
### node app usage
5368
Assumes that you have set the LAUNCHDARKLY_API_TOKEN environment var.
@@ -62,7 +77,7 @@ await ldUtils.toggleFeatureFlag('myProject', 'feature-def', 'dev', true);
6277
```
6378

6479
## commandline modes and parameters
65-
The command line modes and parameters map directly to the functions exposed for use in nodejs apps.
80+
The command line modes and parameters map directly to the functions exposed for use in nodejs apps. This info is also available using `ldutils -help`
6681

6782
### Feature flags
6883

@@ -71,7 +86,11 @@ The command line modes and parameters map directly to the functions exposed for
7186
| getFeatureFlags | projectKey |
7287
| getFeatureFlag | projectKey, featureFlagKey, environmentKeyQuery |
7388
| getFeatureFlagState | projectKey, featureFlagKey, environmentKeyQuery |
89+
| updateFeatureFlag | projectKey, featureFlagKey, patchComment |
7490
| toggleFeatureFlag | projectKey, featureFlagKey, environmentKeyQuery, enabled |
91+
| migrateFeatureFlag | projectKey, featureFlagKey, fromEnv, toEnv, includeState |
92+
93+
> migrateFeatureFlag mode is used to copy flag attributes between environments. This covers: targets, rules, fallthrough, offVariation, prerequisites and optionally the flag on/off state.
7594
7695
### Custom roles
7796

@@ -89,7 +108,7 @@ The command line modes and parameters map directly to the functions exposed for
89108
- `bulkUpsertCustomRoleFolder` mode does the same on a folder of json files.
90109

91110
```
92-
npm run api -- bulkUpsertCustomRoles ./exampleRoleBulkLoad.json
111+
ldutils bulkUpsertCustomRoles ./exampleRoleBulkLoad.json
93112
```
94113

95114
For details on role policy object structures, please see: https://docs.launchdarkly.com/docs/custom-roles

api.js

Lines changed: 0 additions & 211 deletions
This file was deleted.

ldutils

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ new LaunchDarklyUtils().create(process.env.LAUNCHDARKLY_API_TOKEN, log).then(fun
6161
});
6262
});
6363

64+
program
65+
.command(`migrateFeatureFlag <projectKey> <featureFlagKey> <fromEnv> <toEnv> (includeState)`)
66+
.description('migrate flag settings from one environment to another')
67+
.action(function(projectKey, featureFlagKey, fromEnv, toEnv, includeState) {
68+
ldUtils.flags.migrateFeatureFlag(projectKey, featureFlagKey, fromEnv, toEnv, includeState).then(function(response) {
69+
console.log(json.plain(response));
70+
});
71+
});
72+
6473
program
6574
.command('getCustomRoles')
6675
.description('get all custom roles in account')

src/LaunchDarklyApiClient.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
import Swagger from 'swagger-client';
22
import jsYaml from 'js-yaml';
33
import { default as fs } from 'fs';
4+
import { default as json } from 'format-json';
45

56
export class LaunchDarklyApiClient {
67
static async create(API_TOKEN, log) {
78
log.debug(`creating api client with token: ${API_TOKEN}`);
89

910
// swagger.yaml from https://launchdarkly.github.io/ld-openapi/swagger.yaml
10-
const yaml = fs.readFileSync(__dirname + `/../swagger.yaml`, 'utf-8').toString();
11-
const json = jsYaml.safeLoad(yaml);
11+
const swaggerYaml = fs.readFileSync(__dirname + `/../swagger.yaml`, 'utf-8').toString();
12+
const swaggerJson = jsYaml.safeLoad(swaggerYaml);
1213

1314
return Swagger({
14-
spec: json,
15+
spec: swaggerJson,
1516
usePromise: true,
1617
requestInterceptor: req => {
1718
req.headers.Authorization = API_TOKEN;
18-
19-
log.debug(req);
19+
log.debug(`REQUEST: ${json.plain(req)}`);
2020

2121
return req;
22+
},
23+
responseInterceptor: res => {
24+
log.debug(`RESPONSE: ${json.plain(res)}`);
25+
26+
if (res.status !== 200) {
27+
log.debug(`ERROR: ${json.plain(res)}`);
28+
throw res;
29+
}
30+
31+
return res;
2232
}
2333
});
2434
}

0 commit comments

Comments
 (0)