@rockcarver/frodo-cli 0.12.3-1 → 0.12.4-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [0.12.3-1] - 2022-09-01
10
+ ## [0.12.4-1] - 2022-09-08
11
11
 
12
- ## [0.12.3-0] - 2022-09-01
12
+ ## [0.12.4-0] - 2022-09-02
13
+
14
+ ## [0.12.3] - 2022-09-01
15
+
16
+ ### Fixed
17
+
18
+ - \#24 - `frodo conn list` now showing the expected output
19
+ - \#25 - `npm run build` now running properly
13
20
 
14
21
  ## [0.12.2] - 2022-08-27
15
22
 
@@ -21,12 +28,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
21
28
 
22
29
  - \#16: 2nd-level commands in binary builds are working properly again (they were broken in all 0.11.x and 0.12.x builds)
23
30
 
24
- ## [0.12.2-2] - 2022-08-27 [YANKED]
25
-
26
- ## [0.12.2-1] - 2022-08-27 [YANKED]
27
-
28
- ## [0.12.2-0] - 2022-08-27 [YANKED]
29
-
30
31
  ## [0.12.1] - 2022-08-27 [YANKED]
31
32
 
32
33
  ## [0.12.0] - 2022-08-27 [YANKED]
@@ -453,7 +454,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
453
454
  - Fixed problem with adding connection profiles
454
455
  - Miscellaneous bug fixes
455
456
 
456
- [Unreleased]: https://github.com/rockcarver/frodo-cli/compare/v0.12.3-1...HEAD
457
+ [Unreleased]: https://github.com/rockcarver/frodo-cli/compare/v0.12.4-1...HEAD
458
+
459
+ [0.12.4-1]: https://github.com/rockcarver/frodo-cli/compare/v0.12.4-0...v0.12.4-1
460
+
461
+ [0.12.4-0]: https://github.com/rockcarver/frodo-cli/compare/v0.12.3...v0.12.4-0
462
+
463
+ [0.12.3]: https://github.com/rockcarver/frodo-cli/compare/v0.12.3-1...v0.12.3
457
464
 
458
465
  [0.12.3-1]: https://github.com/rockcarver/frodo-cli/compare/v0.12.3-0...v0.12.3-1
459
466
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rockcarver/frodo-cli",
3
- "version": "0.12.3-1",
3
+ "version": "0.12.4-1",
4
4
  "type": "module",
5
5
  "description": "A command line interface to manage ForgeRock Identity Cloud tenants, ForgeOps deployments, and classic deployments.",
6
6
  "keywords": [
@@ -85,12 +85,13 @@
85
85
  },
86
86
  "dependencies": {
87
87
  "@colors/colors": "^1.5.0",
88
- "@rockcarver/frodo-lib": "~0.12.1",
88
+ "@rockcarver/frodo-lib": "0.12.2-1",
89
89
  "cli-progress": "^3.11.2",
90
90
  "cli-table3": "^0.6.2",
91
91
  "commander": "^9.4.0",
92
92
  "nanospinner": "^1.1.0",
93
- "uuid": "^8.3.2"
93
+ "uuid": "^8.3.2",
94
+ "yesno": "^0.4.0"
94
95
  },
95
96
  "devDependencies": {
96
97
  "@babel/eslint-parser": "^7.18.9",
@@ -1,9 +1,17 @@
1
1
  import { Command, Option } from 'commander';
2
- import { Authenticate, Startup, state } from '@rockcarver/frodo-lib';
2
+ import {
3
+ Authenticate,
4
+ Startup,
5
+ ManagedObject,
6
+ state,
7
+ } from '@rockcarver/frodo-lib';
8
+ import yesno from 'yesno';
3
9
  import * as common from '../cmd_common.js';
10
+ import { createTable, printMessage } from '../../utils/Console.js';
4
11
 
5
12
  const { getTokens } = Authenticate;
6
13
  const { applyUpdates, checkForUpdates } = Startup;
14
+ const { resolveUserName } = ManagedObject;
7
15
 
8
16
  const program = new Command('frodo esv apply');
9
17
 
@@ -37,6 +45,12 @@ program
37
45
  'Verbose output during command execution. If specified, may or may not produce additional output.'
38
46
  ).default(false, 'off')
39
47
  )
48
+ .addOption(
49
+ new Option(
50
+ '--timeout <seconds>',
51
+ 'Specify a timeout in seconds how long the tool should wait for the apply command to finish. Only effective without --no-wait.'
52
+ ).default(600, '600 secs (10 mins)')
53
+ )
40
54
  .addOption(new Option('-y, --yes', 'Answer y/yes to all prompts.'))
41
55
  .action(
42
56
  // implement command logic inside action handler
@@ -48,15 +62,55 @@ program
48
62
  state.default.session.setDeploymentType(options.type);
49
63
  state.default.session.setAllowInsecureConnection(options.insecure);
50
64
  if (await getTokens()) {
51
- // check for updates only
52
- if (options.checkOnly) {
53
- console.log(`Checking for updates...`);
54
- await checkForUpdates();
65
+ const updates = await checkForUpdates();
66
+ const updatesTable = createTable([
67
+ 'Type',
68
+ 'Name',
69
+ 'Modified',
70
+ 'Modifier',
71
+ ]);
72
+ for (const secret of updates.secrets) {
73
+ if (!secret.loaded) {
74
+ updatesTable.push([
75
+ 'secret',
76
+ secret._id,
77
+ new Date(secret.lastChangeDate).toLocaleString(),
78
+ // eslint-disable-next-line no-await-in-loop
79
+ await resolveUserName('teammember', secret.lastChangedBy),
80
+ ]);
81
+ }
82
+ }
83
+ for (const variable of updates.variables) {
84
+ if (!variable.loaded) {
85
+ updatesTable.push([
86
+ 'variable',
87
+ variable._id,
88
+ new Date(variable.lastChangeDate).toLocaleString(),
89
+ // eslint-disable-next-line no-await-in-loop
90
+ await resolveUserName('teammember', variable.lastChangedBy),
91
+ ]);
92
+ }
93
+ }
94
+ if (updatesTable.length > 0) {
95
+ printMessage(updatesTable.toString(), 'data');
55
96
  }
56
- // apply updates
57
- else {
58
- console.log(`Applying updates...`);
59
- await applyUpdates(options.force, options.wait, options.yes);
97
+ if (!options.checkOnly) {
98
+ if (
99
+ updates.secrets?.length ||
100
+ updates.variables?.length ||
101
+ options.force
102
+ ) {
103
+ const ok =
104
+ options.yes ||
105
+ (await yesno({
106
+ question: `\nChanges may take up to 10 minutes to propagate, during which time you will not be able to make further updates.\n\nApply updates? (y|n):`,
107
+ }));
108
+ if (ok) {
109
+ if (!(await applyUpdates(options.wait, options.timeout * 1000))) {
110
+ process.exitCode = 1;
111
+ }
112
+ }
113
+ }
60
114
  }
61
115
  }
62
116
  }
@@ -4,7 +4,7 @@ import { Authenticate, Journey, state } from '@rockcarver/frodo-lib';
4
4
  import * as common from '../cmd_common.js';
5
5
 
6
6
  const { getTokens } = Authenticate;
7
- const { listJourneys, getJourneyData, describeTree } = Journey;
7
+ const { getJourneys, exportTree, describeTree } = Journey;
8
8
 
9
9
  const program = new Command('frodo journey describe');
10
10
 
@@ -14,7 +14,7 @@ program
14
14
  )
15
15
  .helpOption('-h, --help', 'Help')
16
16
  .showHelpAfterError()
17
- .addArgument(common.hostArgumentM)
17
+ .addArgument(common.hostArgument)
18
18
  .addArgument(common.realmArgument)
19
19
  .addArgument(common.userArgument)
20
20
  .addArgument(common.passwordArgument)
@@ -47,62 +47,49 @@ program
47
47
  state.default.session.setPassword(password);
48
48
  state.default.session.setDeploymentType(options.type);
49
49
  state.default.session.setAllowInsecureConnection(options.insecure);
50
- const treeDescription = [];
51
50
  // TODO: review checks for arguments
52
51
  if (typeof host === 'undefined' || typeof options.file !== 'undefined') {
53
- if (typeof options.file === 'undefined') {
54
- console.log(
55
- 'You either need <host> or -f when using describe',
56
- 'error'
57
- );
52
+ if (
53
+ typeof host === 'undefined' &&
54
+ typeof options.file === 'undefined'
55
+ ) {
56
+ console.log('Need either [host] or -f.');
57
+ process.exitCode = 1;
58
58
  return;
59
59
  }
60
60
  console.log(`Describing local journey file ${options.file}...`);
61
61
  try {
62
62
  const data = fs.readFileSync(options.file, 'utf8');
63
63
  const journeyData = JSON.parse(data);
64
- treeDescription.push(describeTree(journeyData));
65
- } catch (err) {
66
- console.log(err, 'error');
64
+ describeTree(journeyData);
65
+ } catch (error) {
66
+ console.log(error.message);
67
+ process.exitCode = 1;
67
68
  }
68
69
  } else if (await getTokens()) {
69
70
  console.log(
70
71
  `Describing journey(s) in realm "${state.default.session.getRealm()}"...`
71
72
  );
72
73
  if (typeof options.journeyId === 'undefined') {
73
- const journeyList = await listJourneys(false);
74
- // createProgressBar(journeyList.length, '');
75
- for (const item of journeyList) {
76
- // eslint-disable-next-line no-await-in-loop
77
- const journeyData = await getJourneyData(item.name);
78
- treeDescription.push(describeTree(journeyData));
79
- // updateProgressBar(`Analyzing journey - ${item.name}`);
74
+ let journeys = [];
75
+ journeys = await getJourneys();
76
+ for (const journey of journeys) {
77
+ try {
78
+ // eslint-disable-next-line no-await-in-loop
79
+ const treeData = await exportTree(journey._id);
80
+ describeTree(treeData);
81
+ } catch (error) {
82
+ console.log(error.message);
83
+ process.exitCode = 1;
84
+ }
80
85
  }
81
- // stopProgressBar('Done');
82
86
  } else {
83
- const journeyData = await getJourneyData(options.journeyId);
84
- treeDescription.push(describeTree(journeyData));
85
- }
86
- }
87
- for (const item of treeDescription) {
88
- console.log(`\nJourney: ${item.treeName}`, 'info');
89
- console.log('========');
90
- console.log('\nNodes:', 'info');
91
- if (Object.entries(item.nodeTypes).length) {
92
- for (const [name, count] of Object.entries(item.nodeTypes)) {
93
- console.log(`- ${name}: ${count}`, 'info');
94
- }
95
- }
96
- if (Object.entries(item.scripts).length) {
97
- console.log('\nScripts:', 'info');
98
- for (const [name, desc] of Object.entries(item.scripts)) {
99
- console.log(`- ${name}: ${desc}`, 'info');
100
- }
101
- }
102
- if (Object.entries(item.emailTemplates).length) {
103
- console.log('\nEmail Templates:', 'info');
104
- for (const [id] of Object.entries(item.emailTemplates)) {
105
- console.log(`- ${id}`, 'info');
87
+ try {
88
+ const treeData = await exportTree(options.journeyId);
89
+ describeTree(treeData);
90
+ } catch (error) {
91
+ console.log(error.message);
92
+ process.exitCode = 1;
106
93
  }
107
94
  }
108
95
  }
@@ -1,9 +1,10 @@
1
1
  import { Command } from 'commander';
2
2
  import { Authenticate, Journey, state } from '@rockcarver/frodo-lib';
3
+ import yesno from 'yesno';
3
4
  import * as common from '../cmd_common.js';
4
5
 
5
6
  const { getTokens } = Authenticate;
6
- const { prune } = Journey;
7
+ const { findOrphanedNodes, removeOrphanedNodes } = Journey;
7
8
 
8
9
  const program = new Command('frodo journey prune');
9
10
 
@@ -32,7 +33,17 @@ program
32
33
  console.log(
33
34
  `Pruning orphaned configuration artifacts in realm "${state.default.session.getRealm()}"...`
34
35
  );
35
- prune();
36
+ const orphanedNodes = await findOrphanedNodes();
37
+ if (orphanedNodes.length > 0) {
38
+ const ok = await yesno({
39
+ question: 'Prune (permanently delete) orphaned nodes? (y|n):',
40
+ });
41
+ if (ok) {
42
+ await removeOrphanedNodes(orphanedNodes);
43
+ }
44
+ } else {
45
+ console.log('No orphaned nodes found.');
46
+ }
36
47
  }
37
48
  }
38
49
  // end command logic inside action handler