@toa.io/cli 0.20.0-dev.9 → 0.20.0
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 +8 -7
- package/readme.md +56 -8
- package/src/commands/call.js +20 -0
- package/src/commands/conceal.js +36 -5
- package/src/commands/env.js +7 -0
- package/src/commands/invoke.js +1 -1
- package/src/commands/key.js +18 -0
- package/src/commands/serve.js +2 -3
- package/src/handlers/call.js +36 -0
- package/src/handlers/compose.js +3 -0
- package/src/handlers/conceal.js +49 -3
- package/src/handlers/env.js +60 -8
- package/src/handlers/key.js +16 -0
- package/src/handlers/reveal.js +4 -4
- package/src/handlers/serve.js +5 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/cli",
|
|
3
|
-
"version": "0.20.0
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Toa CLI",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -22,14 +22,15 @@
|
|
|
22
22
|
"@toa.io/runtime": "*"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@toa.io/console": "0.20.0
|
|
26
|
-
"@toa.io/generic": "0.20.0
|
|
27
|
-
"@toa.io/kubernetes": "0.20.0
|
|
28
|
-
"@toa.io/norm": "0.20.0
|
|
29
|
-
"@toa.io/yaml": "0.20.0
|
|
25
|
+
"@toa.io/console": "0.20.0",
|
|
26
|
+
"@toa.io/generic": "0.20.0",
|
|
27
|
+
"@toa.io/kubernetes": "0.20.0",
|
|
28
|
+
"@toa.io/norm": "0.20.0",
|
|
29
|
+
"@toa.io/yaml": "0.20.0",
|
|
30
30
|
"dotenv": "16.1.1",
|
|
31
31
|
"find-up": "5.0.0",
|
|
32
|
+
"paseto": "3.1.4",
|
|
32
33
|
"yargs": "17.6.2"
|
|
33
34
|
},
|
|
34
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "28fc4b45c224c3683acaaf0e4abd1eb04e07b408"
|
|
35
36
|
}
|
package/readme.md
CHANGED
|
@@ -26,6 +26,22 @@ Run composition.
|
|
|
26
26
|
|
|
27
27
|
> Note that your `localhost` it is accessible from a container as `host.docker.internal`.
|
|
28
28
|
|
|
29
|
+
### call
|
|
30
|
+
|
|
31
|
+
Call endpoint.
|
|
32
|
+
|
|
33
|
+
<dl>
|
|
34
|
+
<dt><code>toa call <endpont> [request]</code></dt>
|
|
35
|
+
<dd>
|
|
36
|
+
<code>endpoint</code> endpoint to call.<br/>
|
|
37
|
+
<code>request</code> Request object.<br/>
|
|
38
|
+
</dd>
|
|
39
|
+
</dl>
|
|
40
|
+
|
|
41
|
+
```shell
|
|
42
|
+
$ toa call dummies.dummy.create "{ input: { name: 'foo' } }"
|
|
43
|
+
```
|
|
44
|
+
|
|
29
45
|
### env
|
|
30
46
|
|
|
31
47
|
Export environment to a `.env` file.
|
|
@@ -35,7 +51,8 @@ Export environment to a `.env` file.
|
|
|
35
51
|
<dd>
|
|
36
52
|
<code>environment</code> deployment environment name (default <code>local</code>).<br/>
|
|
37
53
|
<code>--path</code> path to a Context (default <code>.</code>)<br/>
|
|
38
|
-
<code>--as</code> output file path (default <code>.env</code>)
|
|
54
|
+
<code>--as</code> output file path (default <code>.env</code>)<br/>
|
|
55
|
+
<code>--interactive</code> prompt for secret values
|
|
39
56
|
</dd>
|
|
40
57
|
</dl>
|
|
41
58
|
|
|
@@ -72,7 +89,8 @@ $ toa replay ./path/to/context
|
|
|
72
89
|
$ toa replay --title "should add numbers"
|
|
73
90
|
```
|
|
74
91
|
|
|
75
|
-
If the path is a Context root (containing `context.toa.yaml` file), samples for components within
|
|
92
|
+
If the path is a Context root (containing `context.toa.yaml` file), samples for components within
|
|
93
|
+
the Context will be
|
|
76
94
|
found and replayed sequentially.
|
|
77
95
|
|
|
78
96
|
### export manifest
|
|
@@ -88,7 +106,7 @@ found and replayed sequentially.
|
|
|
88
106
|
|
|
89
107
|
## Operations
|
|
90
108
|
|
|
91
|
-
> Some commands use current
|
|
109
|
+
> Some commands use current `kubectl` and `docker` context.
|
|
92
110
|
|
|
93
111
|
### build
|
|
94
112
|
|
|
@@ -124,12 +142,28 @@ Pods [are ready](https://helm.sh/docs/intro/using_helm/#helpful-options-for-inst
|
|
|
124
142
|
|
|
125
143
|
### conceal
|
|
126
144
|
|
|
127
|
-
Deploy a
|
|
145
|
+
Deploy a generic Kubernetes secret with the prefix `toa-`.
|
|
128
146
|
|
|
129
147
|
<dl>
|
|
130
|
-
<dt><code>toa conceal <secret> <key
|
|
148
|
+
<dt><code>toa conceal <secret> <key-values...></code></dt>
|
|
149
|
+
<dd>
|
|
150
|
+
<code>secret</code> Secret name.<br/>
|
|
151
|
+
<code>key-values</code> List of keys and values of the secret as <code>key=value</code>.<br/>
|
|
152
|
+
<code>--namespace</code> Kubernetes namespace where the secret should be deployed.<br/>
|
|
153
|
+
<code>--interactive</code> prompt for secret values<br/>
|
|
154
|
+
<code>--environment</code> environment name for interactive mode<br/>
|
|
155
|
+
<code>--path</code> path to a context for interactive mode
|
|
156
|
+
</dd>
|
|
131
157
|
</dl>
|
|
132
158
|
|
|
159
|
+
> If a secret already exists, then given `key-values` will be added to it.
|
|
160
|
+
|
|
161
|
+
#### Example
|
|
162
|
+
|
|
163
|
+
```shell
|
|
164
|
+
$ toa conceal bindings-amqp-default username=developer password=secret
|
|
165
|
+
```
|
|
166
|
+
|
|
133
167
|
### reveal
|
|
134
168
|
|
|
135
169
|
Outputs keys and values of a secret.
|
|
@@ -149,12 +183,26 @@ Run interactive shell inside a disposable pod inside a Kubernetes cluster.
|
|
|
149
183
|
<code>toa shell [image]</code>
|
|
150
184
|
</dt>
|
|
151
185
|
<dd>
|
|
152
|
-
<code>image</code> Docker image<br/>
|
|
186
|
+
<code>image</code> Docker image to Run (default <code>alpine</code>).<br/>
|
|
153
187
|
</dd>
|
|
154
188
|
</dl>
|
|
155
189
|
|
|
156
|
-
|
|
190
|
+
#### Examples
|
|
157
191
|
|
|
158
192
|
```shell
|
|
159
|
-
$ toa shell
|
|
193
|
+
$ toa shell mongo
|
|
194
|
+
$ toa shell -- ping 1.1 # extra arguments can be passed
|
|
160
195
|
```
|
|
196
|
+
|
|
197
|
+
### key
|
|
198
|
+
|
|
199
|
+
Generate a secret PASETO key.
|
|
200
|
+
|
|
201
|
+
<dl>
|
|
202
|
+
<dt>
|
|
203
|
+
<code>toa key</code>
|
|
204
|
+
</dt>
|
|
205
|
+
<dd>
|
|
206
|
+
<code>--public</code> <code>boolean</code> generate a public/private key pair.<br/>
|
|
207
|
+
</dd>
|
|
208
|
+
</dl>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { call } = require('../handlers/call')
|
|
4
|
+
|
|
5
|
+
const builder = (yargs) => {
|
|
6
|
+
yargs
|
|
7
|
+
.positional('endpoint', {
|
|
8
|
+
type: 'string',
|
|
9
|
+
desc: 'Operation endpoint'
|
|
10
|
+
})
|
|
11
|
+
.positional('request', {
|
|
12
|
+
type: 'string',
|
|
13
|
+
desc: 'Request object'
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.command = 'call <endpoint> [request]'
|
|
18
|
+
exports.desc = 'Call operation'
|
|
19
|
+
exports.builder = builder
|
|
20
|
+
exports.handler = call
|
package/src/commands/conceal.js
CHANGED
|
@@ -7,15 +7,46 @@ const builder = (yargs) => {
|
|
|
7
7
|
.positional('secret', {
|
|
8
8
|
type: 'string'
|
|
9
9
|
})
|
|
10
|
-
.positional('key', {
|
|
11
|
-
type: 'string'
|
|
10
|
+
.positional('key-values', {
|
|
11
|
+
type: 'string',
|
|
12
|
+
array: true,
|
|
13
|
+
desc: 'Secret key-value pairs'
|
|
14
|
+
})
|
|
15
|
+
.option('namespace', {
|
|
16
|
+
alias: 'n',
|
|
17
|
+
group: 'Command options:',
|
|
18
|
+
type: 'string',
|
|
19
|
+
desc: 'Target Kubernetes namespace'
|
|
12
20
|
})
|
|
13
|
-
.
|
|
21
|
+
.option('interactive', {
|
|
22
|
+
alias: 'i',
|
|
23
|
+
group: 'Command options:',
|
|
24
|
+
describe: 'Prompt for secrets',
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
default: false
|
|
27
|
+
})
|
|
28
|
+
.option('environment', {
|
|
29
|
+
alias: 'e',
|
|
30
|
+
group: 'Command options:',
|
|
31
|
+
describe: 'Environment name for interactive mode',
|
|
14
32
|
type: 'string'
|
|
15
33
|
})
|
|
34
|
+
.option('path', {
|
|
35
|
+
alias: 'p',
|
|
36
|
+
group: 'Command options:',
|
|
37
|
+
describe: 'Path to a Context for interactive mode',
|
|
38
|
+
type: 'string',
|
|
39
|
+
default: '.'
|
|
40
|
+
})
|
|
41
|
+
.example([
|
|
42
|
+
['$0 conceal -i'],
|
|
43
|
+
['$0 conceal credentials username=developer'],
|
|
44
|
+
['$0 conceal credentials username=developer password=secret'],
|
|
45
|
+
['$0 conceal credentials username=developer --namespace app']
|
|
46
|
+
])
|
|
16
47
|
}
|
|
17
48
|
|
|
18
|
-
exports.command = 'conceal
|
|
19
|
-
exports.desc = 'Deploy a
|
|
49
|
+
exports.command = 'conceal [secret] [key-values...]'
|
|
50
|
+
exports.desc = 'Deploy a secret'
|
|
20
51
|
exports.builder = builder
|
|
21
52
|
exports.handler = conceal
|
package/src/commands/env.js
CHANGED
|
@@ -22,6 +22,13 @@ const builder = (yargs) => {
|
|
|
22
22
|
type: 'string',
|
|
23
23
|
default: '.env'
|
|
24
24
|
})
|
|
25
|
+
.option('interactive', {
|
|
26
|
+
alias: 'i',
|
|
27
|
+
group: 'Command options:',
|
|
28
|
+
describe: 'Prompt for secrets',
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
default: false
|
|
31
|
+
})
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
exports.command = 'env [environment]'
|
package/src/commands/invoke.js
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { key } = require('../handlers/key')
|
|
4
|
+
|
|
5
|
+
const builder = (yargs) => {
|
|
6
|
+
yargs
|
|
7
|
+
.option('public', {
|
|
8
|
+
group: 'Command options:',
|
|
9
|
+
describe: 'Generate a public/private key pair',
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
default: false
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.command = 'key'
|
|
16
|
+
exports.desc = 'Generate a secret PASETO key'
|
|
17
|
+
exports.builder = builder
|
|
18
|
+
exports.handler = key
|
package/src/commands/serve.js
CHANGED
|
@@ -5,15 +5,14 @@ const { serve } = require('../handlers/serve')
|
|
|
5
5
|
const builder = (yargs) => {
|
|
6
6
|
yargs
|
|
7
7
|
.positional('path', {
|
|
8
|
-
alias: 'p',
|
|
9
8
|
group: 'Command options:',
|
|
10
9
|
type: 'string',
|
|
11
|
-
desc: 'Path
|
|
10
|
+
desc: 'Path or a shortcut of an extension',
|
|
12
11
|
default: '.'
|
|
13
12
|
})
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
exports.command = 'serve [path]'
|
|
17
|
-
exports.desc = 'Run service'
|
|
16
|
+
exports.desc = 'Run an extension service'
|
|
18
17
|
exports.builder = builder
|
|
19
18
|
exports.handler = serve
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Readable } = require('node:stream')
|
|
4
|
+
const boot = require('@toa.io/boot')
|
|
5
|
+
const yaml = require('@toa.io/yaml')
|
|
6
|
+
const { Locator } = require('@toa.io/core')
|
|
7
|
+
|
|
8
|
+
async function call (argv) {
|
|
9
|
+
const [operation, component, namespace = 'default'] = argv.endpoint.split('.').reverse()
|
|
10
|
+
const locator = new Locator(component, namespace)
|
|
11
|
+
const request = argv.request ? yaml.parse(argv.request) : {}
|
|
12
|
+
|
|
13
|
+
const remote = await boot.remote(locator)
|
|
14
|
+
await remote.connect()
|
|
15
|
+
|
|
16
|
+
let reply
|
|
17
|
+
let exception
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
reply = await remote.invoke(operation, request)
|
|
21
|
+
} catch (e) {
|
|
22
|
+
exception = e
|
|
23
|
+
} finally {
|
|
24
|
+
if (exception === undefined) {
|
|
25
|
+
if (reply instanceof Readable) {
|
|
26
|
+
for await (const chunk of reply) console.log(chunk)
|
|
27
|
+
} else console.log(reply)
|
|
28
|
+
} else console.error(exception)
|
|
29
|
+
|
|
30
|
+
await remote.disconnect()
|
|
31
|
+
|
|
32
|
+
if (exception !== undefined) process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.call = call
|
package/src/handlers/compose.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { pick } = require('@toa.io/generic')
|
|
4
4
|
const boot = require('@toa.io/boot')
|
|
5
|
+
const { version } = require('@toa.io/runtime')
|
|
5
6
|
|
|
6
7
|
const docker = require('./docker')
|
|
7
8
|
const { components: find } = require('../util/find')
|
|
@@ -11,6 +12,8 @@ const { components: find } = require('../util/find')
|
|
|
11
12
|
* @return {Promise<void>}
|
|
12
13
|
*/
|
|
13
14
|
async function compose (argv) {
|
|
15
|
+
console.log('Runtime', version)
|
|
16
|
+
|
|
14
17
|
if (argv.dock === true) return dock(argv)
|
|
15
18
|
|
|
16
19
|
const paths = find(argv.paths)
|
package/src/handlers/conceal.js
CHANGED
|
@@ -1,12 +1,58 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { secrets } = require('@toa.io/kubernetes')
|
|
4
|
+
const boot = require('@toa.io/boot')
|
|
5
|
+
const { context: find } = require('../util/find')
|
|
6
|
+
const { promptSecrets } = require('./env')
|
|
4
7
|
|
|
5
8
|
const conceal = async (argv) => {
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
if (argv.interactive) await concealValues(argv)
|
|
10
|
+
else await concealValue(argv)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function concealValue (argv) {
|
|
14
|
+
if (argv['key-values'].length === 0) throw new Error('Key-values must be passed')
|
|
15
|
+
|
|
16
|
+
const values = argv['key-values'].reduce((values, pair) => {
|
|
17
|
+
const [key, value] = pair.split('=')
|
|
18
|
+
|
|
19
|
+
values[key] = value
|
|
20
|
+
|
|
21
|
+
return values
|
|
22
|
+
}, {})
|
|
23
|
+
|
|
24
|
+
const secret = PREFIX + argv.secret
|
|
25
|
+
|
|
26
|
+
await secrets.upsert(secret, values, argv.namespace)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function concealValues (argv) {
|
|
30
|
+
const path = find(argv.path)
|
|
31
|
+
const operator = await boot.deployment(path, argv.environment)
|
|
32
|
+
const variables = operator.variables()
|
|
33
|
+
const values = await promptSecrets(variables)
|
|
34
|
+
const groups = groupValues(values)
|
|
35
|
+
|
|
36
|
+
for (const [secret, values] of Object.entries(groups)) {
|
|
37
|
+
await secrets.upsert(secret, values, argv.namespace)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @return {Record<string, Record<string, string>>}
|
|
43
|
+
*/
|
|
44
|
+
function groupValues (values) {
|
|
45
|
+
const secrets = {}
|
|
46
|
+
|
|
47
|
+
for (const [key, value] of Object.entries(values)) {
|
|
48
|
+
const [secret, variable] = key.split('/')
|
|
49
|
+
|
|
50
|
+
if (!(secret in secrets)) secrets[secret] = {}
|
|
51
|
+
|
|
52
|
+
secrets[secret][variable] = value
|
|
53
|
+
}
|
|
8
54
|
|
|
9
|
-
|
|
55
|
+
return secrets
|
|
10
56
|
}
|
|
11
57
|
|
|
12
58
|
const PREFIX = 'toa-'
|
package/src/handlers/env.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { join } = require('node:path')
|
|
4
|
+
const readline = require('node:readline/promises')
|
|
5
|
+
const { stdin: input, stdout: output } = require('node:process')
|
|
6
|
+
|
|
4
7
|
const dotenv = require('dotenv')
|
|
5
8
|
const { file } = require('@toa.io/filesystem')
|
|
6
9
|
const boot = require('@toa.io/boot')
|
|
@@ -12,13 +15,16 @@ async function env (argv) {
|
|
|
12
15
|
const operator = await boot.deployment(path, argv.environment)
|
|
13
16
|
const variables = operator.variables()
|
|
14
17
|
const currentValues = await read(filepath)
|
|
15
|
-
const values = []
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
const result = merge(variables, currentValues)
|
|
20
|
+
|
|
21
|
+
if (argv.interactive) {
|
|
22
|
+
const secrets = await promptSecrets(result)
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
mergeSecrets(result, secrets)
|
|
25
|
+
}
|
|
20
26
|
|
|
21
|
-
await write(filepath,
|
|
27
|
+
await write(filepath, result)
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
/**
|
|
@@ -41,25 +47,71 @@ async function read (path) {
|
|
|
41
47
|
* @return {Promise<void>}
|
|
42
48
|
*/
|
|
43
49
|
async function write (path, values) {
|
|
44
|
-
const contents = values.reduce((lines, { name, value }) => lines + `${name}=${value}\n`, '')
|
|
50
|
+
const contents = values.reduce((lines, { name, value }) => lines + `${name}=${value ?? ''}\n`, '')
|
|
45
51
|
|
|
46
52
|
await file.write(path, contents)
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/**
|
|
50
|
-
* @param {toa.deployment.dependency.Variable[]
|
|
56
|
+
* @param {toa.deployment.dependency.Variable[]} variables
|
|
51
57
|
* @param {Record<string, string>} current
|
|
52
58
|
* @return {toa.deployment.dependency.Variable[]}
|
|
53
59
|
*/
|
|
54
60
|
function merge (variables, current) {
|
|
55
61
|
return variables.map((variable) => {
|
|
56
|
-
if (variable.secret === undefined) return variable
|
|
62
|
+
if (variable.secret === undefined || !current[variable.name]) return variable
|
|
57
63
|
|
|
58
64
|
return {
|
|
59
65
|
name: variable.name,
|
|
60
|
-
value: current[variable.name]
|
|
66
|
+
value: current[variable.name]
|
|
61
67
|
}
|
|
62
68
|
})
|
|
63
69
|
}
|
|
64
70
|
|
|
71
|
+
async function promptSecrets (variables) {
|
|
72
|
+
const rl = readline.createInterface({ input, output })
|
|
73
|
+
const secrets = {}
|
|
74
|
+
|
|
75
|
+
for (const variable of variables) {
|
|
76
|
+
if (variable.secret === undefined) continue
|
|
77
|
+
|
|
78
|
+
const key = getKey(variable.secret)
|
|
79
|
+
|
|
80
|
+
secrets[key] = await promptSecret(key, rl)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
rl.close()
|
|
84
|
+
|
|
85
|
+
return secrets
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function promptSecret (key, rl) {
|
|
89
|
+
if (SECRETS[key] === undefined) SECRETS[key] = await rl.question(`${key}: `)
|
|
90
|
+
|
|
91
|
+
return SECRETS[key]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {toa.deployment.dependency.Variable[]} variables
|
|
96
|
+
* @param {Record<string, string>} secrets
|
|
97
|
+
*/
|
|
98
|
+
function mergeSecrets (variables, secrets) {
|
|
99
|
+
for (const variable of variables) {
|
|
100
|
+
if (variable.secret === undefined) continue
|
|
101
|
+
|
|
102
|
+
const key = getKey(variable.secret)
|
|
103
|
+
|
|
104
|
+
variable.value = secrets[key]
|
|
105
|
+
|
|
106
|
+
delete variable.secret
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getKey (secret) {
|
|
111
|
+
return `${secret.name}/${secret.key}`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const SECRETS = {}
|
|
115
|
+
|
|
65
116
|
exports.env = env
|
|
117
|
+
exports.promptSecrets = promptSecrets
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { V3 } = require('paseto')
|
|
4
|
+
|
|
5
|
+
async function key (argv) {
|
|
6
|
+
const purpose = argv.public ? 'public' : 'local'
|
|
7
|
+
const key = await V3.generateKey(purpose, { format: 'paserk' })
|
|
8
|
+
|
|
9
|
+
if (argv.public) {
|
|
10
|
+
console.log(key.secretKey)
|
|
11
|
+
console.log(key.publicKey)
|
|
12
|
+
} else
|
|
13
|
+
console.log(key)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.key = key
|
package/src/handlers/reveal.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { secrets } = require('@toa.io/kubernetes')
|
|
4
|
-
const { remap, decode } = require('@toa.io/generic')
|
|
5
4
|
|
|
6
5
|
const { PREFIX } = require('./conceal')
|
|
7
6
|
|
|
8
7
|
const reveal = async (argv) => {
|
|
9
8
|
const prefixed = PREFIX + argv.secret
|
|
10
|
-
const
|
|
11
|
-
const values = remap(secret.data, decode)
|
|
9
|
+
const data = await secrets.get(prefixed)
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
if (data === null) return
|
|
12
|
+
|
|
13
|
+
for (const [key, value] of Object.entries(data)) {
|
|
14
14
|
const line = `${key}: ${value}`
|
|
15
15
|
|
|
16
16
|
console.log(line)
|
package/src/handlers/serve.js
CHANGED
|
@@ -3,21 +3,22 @@
|
|
|
3
3
|
const boot = require('@toa.io/boot')
|
|
4
4
|
const { shortcuts } = require('@toa.io/norm')
|
|
5
5
|
const { directory: { find } } = require('@toa.io/filesystem')
|
|
6
|
+
const { version } = require('@toa.io/runtime')
|
|
6
7
|
|
|
7
8
|
const serve = async (argv) => {
|
|
9
|
+
console.log('Runtime', version)
|
|
10
|
+
|
|
8
11
|
argv.path = shortcuts.resolve(argv.path)
|
|
9
12
|
|
|
10
13
|
const module = find(argv.path, process.cwd())
|
|
11
14
|
|
|
12
15
|
const { Factory } = require(module)
|
|
13
16
|
|
|
14
|
-
/** @type {toa.core.extensions.Factory} */
|
|
15
17
|
const factory = new Factory(boot)
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
const service = factory.service()
|
|
19
|
+
if (factory.service === undefined) throw new Error(`Service is not implemented by ${argv.path}`)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
const service = factory.service()
|
|
21
22
|
|
|
22
23
|
await service.connect()
|
|
23
24
|
|