@toa.io/cli 1.0.0-alpha.5 → 1.0.0-alpha.51
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/package.json +9 -8
- package/readme.md +10 -35
- package/src/commands/export/manifest.js +6 -0
- package/src/commands/export/secrets.js +23 -0
- package/src/handlers/compose.js +3 -0
- package/src/handlers/docker/build.js +7 -3
- package/src/handlers/export/manifest.js +5 -1
- package/src/handlers/export/secrets.js +41 -0
- package/src/handlers/lib/graceful.js +12 -0
- package/src/handlers/serve.js +2 -2
- package/src/commands/export/entity.js +0 -26
- package/src/commands/replay.js +0 -66
- package/src/handlers/export/entity.js +0 -27
- package/src/handlers/replay.js +0 -64
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.51",
|
|
4
4
|
"description": "Toa CLI",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -22,16 +22,17 @@
|
|
|
22
22
|
"@toa.io/runtime": "*"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@toa.io/console": "1.0.0-alpha.
|
|
26
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
27
|
-
"@toa.io/kubernetes": "1.0.0-alpha.
|
|
28
|
-
"@toa.io/norm": "1.0.0-alpha.
|
|
29
|
-
"@toa.io/operations": "1.0.0-alpha.
|
|
30
|
-
"@toa.io/yaml": "1.0.0-alpha.
|
|
25
|
+
"@toa.io/console": "1.0.0-alpha.51",
|
|
26
|
+
"@toa.io/generic": "1.0.0-alpha.51",
|
|
27
|
+
"@toa.io/kubernetes": "1.0.0-alpha.51",
|
|
28
|
+
"@toa.io/norm": "1.0.0-alpha.51",
|
|
29
|
+
"@toa.io/operations": "1.0.0-alpha.51",
|
|
30
|
+
"@toa.io/yaml": "1.0.0-alpha.51",
|
|
31
31
|
"dotenv": "16.1.1",
|
|
32
32
|
"find-up": "5.0.0",
|
|
33
|
+
"jsonpath": "1.1.1",
|
|
33
34
|
"paseto": "3.1.4",
|
|
34
35
|
"yargs": "17.6.2"
|
|
35
36
|
},
|
|
36
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "ac4d10842dd1e1013f1b645f5d176ae545696d8c"
|
|
37
38
|
}
|
package/readme.md
CHANGED
|
@@ -60,53 +60,28 @@ Credentials specified in the output file are preserved.
|
|
|
60
60
|
|
|
61
61
|
> It is recommended to add `.env*` to `.gitignore`.
|
|
62
62
|
|
|
63
|
-
### replay
|
|
64
|
-
|
|
65
|
-
[Replay](/extensions/sampling/docs/replay.md) samples. Reports in [TAP](https://testanything.org)
|
|
66
|
-
format.
|
|
67
|
-
|
|
68
|
-
<dl>
|
|
69
|
-
<dt><code>toa replay [paths...]</code></dt>
|
|
70
|
-
<dd>
|
|
71
|
-
<code>paths</code> Path(s) to Component(s) or a Context (default <code>.</code>).<br/>
|
|
72
|
-
<code>--component <id></code> Replay samples for a specified component <code>id</code>.<br/>
|
|
73
|
-
<code>--integration</code> Replay integration tests only.<br/>
|
|
74
|
-
<code>--autonomous</code> Replay autonomous tests only.<br/>
|
|
75
|
-
<code>--operation <name></code> Replay samples for specified operation.<br/>
|
|
76
|
-
<code>--title <regexp></code> Regexp to match sample titles.<br/>
|
|
77
|
-
<code>--dock</code> Run in Docker. Applicable only for component samples.
|
|
78
|
-
</dd>
|
|
79
|
-
</dl>
|
|
80
|
-
|
|
81
|
-
#### Examples
|
|
82
|
-
|
|
83
|
-
```shell
|
|
84
|
-
$ toa replay
|
|
85
|
-
$ toa replay ./path/to/component
|
|
86
|
-
$ toa replay ./components/a ./components/b --dock
|
|
87
|
-
$ toa replay ./components/*
|
|
88
|
-
$ toa replay ./path/to/context
|
|
89
|
-
$ toa replay --title "should add numbers"
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
If the path is a Context root (containing `context.toa.yaml` file), samples for components within
|
|
93
|
-
the Context will be found and replayed sequentially.
|
|
94
|
-
|
|
95
63
|
### export manifest
|
|
96
64
|
|
|
97
65
|
<dl>
|
|
98
66
|
<dt><code>toa export manifest</code></dt>
|
|
99
67
|
<dd>Print normalized manifest.
|
|
100
68
|
|
|
101
|
-
<code>--path</code> path to component (default <code>.</code>)<br/>
|
|
69
|
+
<code>--path</code> path to a component (default <code>.</code>)<br/>
|
|
70
|
+
<code>--jsonpath</code> JSONPath expression to filter the output<br/>
|
|
102
71
|
<code>--error</code> print errors only<br/>
|
|
103
72
|
<code>--output</code> output format (default <code>yaml</code>)
|
|
104
73
|
</dd>
|
|
105
74
|
</dl>
|
|
106
75
|
|
|
107
|
-
### export
|
|
76
|
+
### export secrets
|
|
108
77
|
|
|
109
|
-
|
|
78
|
+
<dl>
|
|
79
|
+
<dt><code>toa export secrets <environment></code></dt>
|
|
80
|
+
<dd>Print deployment secrets.
|
|
81
|
+
|
|
82
|
+
<code>--path</code> path to context (default <code>.</code>)<br/>
|
|
83
|
+
</dd>
|
|
84
|
+
</dl>
|
|
110
85
|
|
|
111
86
|
## Operations
|
|
112
87
|
|
|
@@ -17,6 +17,12 @@ const builder = (yargs) => {
|
|
|
17
17
|
desc: 'Path to a component',
|
|
18
18
|
default: '.'
|
|
19
19
|
})
|
|
20
|
+
.option('jsonpath', {
|
|
21
|
+
alias: 'j',
|
|
22
|
+
group: 'Command options:',
|
|
23
|
+
type: 'string',
|
|
24
|
+
desc: 'JSONPath expression'
|
|
25
|
+
})
|
|
20
26
|
.option('output', {
|
|
21
27
|
alias: 'o',
|
|
22
28
|
group: 'Command options:',
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { secrets } = require('../../handlers/export/secrets')
|
|
4
|
+
|
|
5
|
+
const builder = (yargs) => {
|
|
6
|
+
yargs
|
|
7
|
+
.positional('environment', {
|
|
8
|
+
type: 'string',
|
|
9
|
+
desc: 'Deployment environment'
|
|
10
|
+
})
|
|
11
|
+
.option('path', {
|
|
12
|
+
alias: 'p',
|
|
13
|
+
group: 'Command options:',
|
|
14
|
+
type: 'string',
|
|
15
|
+
desc: 'Path to context',
|
|
16
|
+
default: '.'
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.command = ['secrets <environment>']
|
|
21
|
+
exports.desc = 'Export deployment secrets'
|
|
22
|
+
exports.builder = builder
|
|
23
|
+
exports.handler = secrets
|
package/src/handlers/compose.js
CHANGED
|
@@ -5,6 +5,7 @@ const boot = require('@toa.io/boot')
|
|
|
5
5
|
const { version } = require('@toa.io/runtime')
|
|
6
6
|
|
|
7
7
|
const docker = require('./docker')
|
|
8
|
+
const { graceful } = require('./lib/graceful')
|
|
8
9
|
const { components: find } = require('../util/find')
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -22,6 +23,8 @@ async function compose (argv) {
|
|
|
22
23
|
await composition.connect()
|
|
23
24
|
|
|
24
25
|
if (argv.kill === true) await composition.disconnect()
|
|
26
|
+
|
|
27
|
+
return graceful(composition)
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
/**
|
|
@@ -14,8 +14,9 @@ async function build (contextPath, componentPatterns) {
|
|
|
14
14
|
await registry.build()
|
|
15
15
|
|
|
16
16
|
const composition = context.compositions[0].name
|
|
17
|
+
const base = context.registry.base === undefined ? '' : context.registry.base + '/'
|
|
17
18
|
|
|
18
|
-
return `${
|
|
19
|
+
return `${base}${context.name}/composition-${composition}`
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
async function createContext (contextPath, componentPatterns) {
|
|
@@ -24,10 +25,13 @@ async function createContext (contextPath, componentPatterns) {
|
|
|
24
25
|
const paths = componentPatterns.map((pattern) => find.components(pattern))
|
|
25
26
|
const components = await loadComponents(paths)
|
|
26
27
|
const rnd = newid().substring(0, 6)
|
|
27
|
-
const name = '
|
|
28
|
+
const name = 'temp-' + rnd
|
|
28
29
|
|
|
29
30
|
context.name += '-' + rnd
|
|
30
|
-
context.compositions = [{
|
|
31
|
+
context.compositions = [{
|
|
32
|
+
name,
|
|
33
|
+
components
|
|
34
|
+
}]
|
|
31
35
|
|
|
32
36
|
return context
|
|
33
37
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const jsonpath = require('jsonpath')
|
|
3
4
|
const { component } = require('@toa.io/norm')
|
|
4
5
|
const { console } = require('@toa.io/console')
|
|
5
6
|
const yaml = require('@toa.io/yaml')
|
|
@@ -11,7 +12,10 @@ const print = async (argv) => {
|
|
|
11
12
|
|
|
12
13
|
if (path === undefined) throw new Error(`No component found in ${argv.path}`)
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
let manifest = await component(path)
|
|
16
|
+
|
|
17
|
+
if (argv.jsonpath !== undefined)
|
|
18
|
+
manifest = jsonpath.value(manifest, argv.jsonpath)
|
|
15
19
|
|
|
16
20
|
if (argv.error !== true) {
|
|
17
21
|
const result = argv.output === 'json'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { console } = require('@toa.io/console')
|
|
4
|
+
const { context: find } = require('../../util/find')
|
|
5
|
+
const { deployment: { Factory } } = require('@toa.io/operations')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {{ path: string, target: string, environment?: string }} argv
|
|
9
|
+
* @returns {Promise<void>}
|
|
10
|
+
*/
|
|
11
|
+
const secrets = async (argv) => {
|
|
12
|
+
const path = find(argv.path)
|
|
13
|
+
const factory = await Factory.create(path, argv.environment)
|
|
14
|
+
const operator = factory.operator()
|
|
15
|
+
const secrets = operator
|
|
16
|
+
.variables()
|
|
17
|
+
.filter(({ secret }) => secret !== undefined)
|
|
18
|
+
.map(({ secret }) => secret)
|
|
19
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
20
|
+
|
|
21
|
+
const groups = []
|
|
22
|
+
let current = null
|
|
23
|
+
|
|
24
|
+
for (const secret of secrets) {
|
|
25
|
+
if (current === null || current.name !== secret.name) {
|
|
26
|
+
current = { name: secret.name, keys: new Set() }
|
|
27
|
+
groups.push(current)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
current.keys.add(secret.key)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const group of groups) {
|
|
34
|
+
console.log(`${group.name}:`)
|
|
35
|
+
|
|
36
|
+
for (const key of group.keys)
|
|
37
|
+
console.log(' ' + key)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.secrets = secrets
|
package/src/handlers/serve.js
CHANGED
|
@@ -4,6 +4,7 @@ const boot = require('@toa.io/boot')
|
|
|
4
4
|
const { shortcuts } = require('@toa.io/norm')
|
|
5
5
|
const { directory: { find } } = require('@toa.io/filesystem')
|
|
6
6
|
const { version } = require('@toa.io/runtime')
|
|
7
|
+
const { graceful } = require('./lib/graceful')
|
|
7
8
|
|
|
8
9
|
const serve = async (argv) => {
|
|
9
10
|
console.log('Runtime', version)
|
|
@@ -22,8 +23,7 @@ const serve = async (argv) => {
|
|
|
22
23
|
|
|
23
24
|
await service.connect()
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
return service
|
|
26
|
+
return graceful(service)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
exports.serve = serve
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { manifest } = require('../../handlers/export/entity')
|
|
4
|
-
|
|
5
|
-
const builder = (yargs) => {
|
|
6
|
-
yargs
|
|
7
|
-
.option('path', {
|
|
8
|
-
alias: 'p',
|
|
9
|
-
group: 'Command options:',
|
|
10
|
-
type: 'string',
|
|
11
|
-
desc: 'Path to a component',
|
|
12
|
-
default: '.'
|
|
13
|
-
})
|
|
14
|
-
.option('output', {
|
|
15
|
-
alias: 'o',
|
|
16
|
-
group: 'Command options:',
|
|
17
|
-
choices: ['yaml', 'json'],
|
|
18
|
-
desc: 'Output format',
|
|
19
|
-
default: 'yaml'
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
exports.command = 'entity'
|
|
24
|
-
exports.desc = 'Print entity'
|
|
25
|
-
exports.builder = builder
|
|
26
|
-
exports.handler = manifest
|
package/src/commands/replay.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
// noinspection JSCheckFunctionSignatures
|
|
2
|
-
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
|
-
const { replay } = require('../handlers/replay')
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
!!! OPTIONS MUST BE SYNCHRONIZED WITH ../handlers/.replay/args !!!
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const builder = (yargs) => {
|
|
12
|
-
yargs
|
|
13
|
-
.positional('paths', {
|
|
14
|
-
type: 'string',
|
|
15
|
-
desc: 'Paths to components or context',
|
|
16
|
-
default: '.'
|
|
17
|
-
})
|
|
18
|
-
.option('component', {
|
|
19
|
-
alias: 'c',
|
|
20
|
-
type: 'string',
|
|
21
|
-
group: 'Command options:',
|
|
22
|
-
describe: 'Replay samples for specified component'
|
|
23
|
-
})
|
|
24
|
-
.option('autonomous', {
|
|
25
|
-
alias: 'a',
|
|
26
|
-
type: 'boolean',
|
|
27
|
-
group: 'Command options:',
|
|
28
|
-
describe: 'Replay autonomous tests only'
|
|
29
|
-
})
|
|
30
|
-
.option('integration', {
|
|
31
|
-
alias: 'i',
|
|
32
|
-
type: 'boolean',
|
|
33
|
-
group: 'Command options:',
|
|
34
|
-
describe: 'Replay integration tests only'
|
|
35
|
-
})
|
|
36
|
-
.option('operation', {
|
|
37
|
-
alias: 'o',
|
|
38
|
-
type: 'string',
|
|
39
|
-
group: 'Command options:',
|
|
40
|
-
describe: 'Replay samples for specified operation'
|
|
41
|
-
})
|
|
42
|
-
.option('title', {
|
|
43
|
-
alias: 't',
|
|
44
|
-
type: 'string',
|
|
45
|
-
group: 'Command options:',
|
|
46
|
-
describe: 'Replay samples with titles matching given regexp'
|
|
47
|
-
})
|
|
48
|
-
.option('dock', {
|
|
49
|
-
alias: 'd',
|
|
50
|
-
type: 'boolean',
|
|
51
|
-
default: false,
|
|
52
|
-
group: 'Command options:',
|
|
53
|
-
describe: 'Replay inside Docker container'
|
|
54
|
-
})
|
|
55
|
-
.option('context', {
|
|
56
|
-
group: 'Command options:',
|
|
57
|
-
type: 'string',
|
|
58
|
-
desc: 'Path to the Context (used with --dock)',
|
|
59
|
-
default: '.'
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
exports.command = 'replay [paths...]'
|
|
64
|
-
exports.desc = 'Replay samples'
|
|
65
|
-
exports.builder = builder
|
|
66
|
-
exports.handler = replay
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { component } = require('@toa.io/norm')
|
|
4
|
-
const { console } = require('@toa.io/console')
|
|
5
|
-
const yaml = require('@toa.io/yaml')
|
|
6
|
-
|
|
7
|
-
const { components: find } = require('../../util/find')
|
|
8
|
-
|
|
9
|
-
const print = async (argv) => {
|
|
10
|
-
const path = find(argv.path)
|
|
11
|
-
|
|
12
|
-
if (path === undefined) throw new Error(`No component found in ${argv.path}`)
|
|
13
|
-
|
|
14
|
-
const manifest = await component(path)
|
|
15
|
-
const entity = manifest.entity
|
|
16
|
-
|
|
17
|
-
if (entity === undefined)
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
const result = argv.output === 'json'
|
|
21
|
-
? JSON.stringify(entity, null, 2)
|
|
22
|
-
: yaml.dump(entity)
|
|
23
|
-
|
|
24
|
-
console.log(result)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
exports.manifest = print
|
package/src/handlers/replay.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { pick } = require('@toa.io/generic')
|
|
4
|
-
const { context, components } = require('@toa.io/userland/samples')
|
|
5
|
-
|
|
6
|
-
const find = require('../util/find')
|
|
7
|
-
const docker = require('./docker')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param {Record<string, string | string[] | boolean>} argv
|
|
11
|
-
* @return {Promise<void>}
|
|
12
|
-
*/
|
|
13
|
-
async function replay (argv) {
|
|
14
|
-
if (argv.dock) return dock(argv)
|
|
15
|
-
|
|
16
|
-
/** @type {boolean} */
|
|
17
|
-
let ok
|
|
18
|
-
|
|
19
|
-
const paths = find.components(argv.paths, true)
|
|
20
|
-
|
|
21
|
-
/** @type {toa.samples.suite.Options} */
|
|
22
|
-
const options = {
|
|
23
|
-
component: argv.component,
|
|
24
|
-
autonomous: argv.autonomous,
|
|
25
|
-
integration: argv.integration,
|
|
26
|
-
operation: argv.operation,
|
|
27
|
-
title: argv.title,
|
|
28
|
-
runner: { bail: true }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (paths !== null) {
|
|
32
|
-
ok = await components(paths, options)
|
|
33
|
-
} else {
|
|
34
|
-
// no components found, checking context
|
|
35
|
-
const path = find.context(argv.paths[0], true)
|
|
36
|
-
|
|
37
|
-
if (path === null) throw new Error('Neither components nor context found in ' + argv.paths.join(','))
|
|
38
|
-
|
|
39
|
-
ok = await context(path, options)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const message = (ok ? GREEN + 'PASSED' : RED + 'FAILED') + RESET
|
|
43
|
-
|
|
44
|
-
// print after tap's output
|
|
45
|
-
process.on('beforeExit', () => console.log(message))
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param {Record<string, string | string[] | boolean>} argv
|
|
50
|
-
* @return {Promise<void>}
|
|
51
|
-
*/
|
|
52
|
-
async function dock (argv) {
|
|
53
|
-
const repository = await docker.build(argv.context, argv.paths)
|
|
54
|
-
const args = pick(argv, ['component', 'operation', 'integration', 'title'])
|
|
55
|
-
const command = docker.command('toa replay *', args)
|
|
56
|
-
|
|
57
|
-
await docker.run(repository, command, argv.env)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const GREEN = '\x1b[32m'
|
|
61
|
-
const RED = '\x1b[31m'
|
|
62
|
-
const RESET = '\x1b[0m'
|
|
63
|
-
|
|
64
|
-
exports.replay = replay
|