1 | const yargs = require('yargs');
|
2 |
|
3 | const logger = require('./lib/logger');
|
4 | const { parseTimeString } = require('./lib/timeUtil');
|
5 | const { deployHandler, createHandler, invokeHandler, listHandler,
|
6 | logsHandler, loginHandler, removeHandler, perfHandler } = require('./lib');
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | const msgAndExit = function msgAndExit(message, displayHelp) {
|
16 | if (displayHelp) yargs.showHelp();
|
17 | logger.error(message);
|
18 | process.exit(1);
|
19 | };
|
20 |
|
21 | const handleCommand = async function handleCommand(options, specificHandler) {
|
22 | const cmdSeq = options._;
|
23 |
|
24 | if (cmdSeq.length > 1) {
|
25 | msgAndExit(`Invalid subcommand ${cmdSeq[1]} for command ${cmdSeq[0]}`, true);
|
26 | }
|
27 |
|
28 | await specificHandler(options);
|
29 | process.exit(0);
|
30 | };
|
31 |
|
32 | const runtimes = require('./lib/runtimes');
|
33 |
|
34 | yargs
|
35 | .option('path', {
|
36 | alias: 'p',
|
37 | describe: 'Use directory dir. "create" will create this directory if needed.',
|
38 | type: 'string',
|
39 | global: true,
|
40 | })
|
41 | .usage(
|
42 | `Binaris command line interface
|
43 |
|
44 | Usage: $0 <command> [options]`
|
45 | )
|
46 | .command('create <runtime> <function> [options]', 'Create a function from template', (yargs0) => {
|
47 | yargs0
|
48 | .usage('Usage: $0 create <runtime> <function> [options]')
|
49 | .positional('runtime', {
|
50 | choices: runtimes,
|
51 | type: 'string',
|
52 | })
|
53 | .positional('function', {
|
54 | describe: 'Function name',
|
55 | type: 'string',
|
56 | });
|
57 | }, async (argv) => {
|
58 | await handleCommand(argv, createHandler);
|
59 | })
|
60 | .command('deploy <function> [options]', 'Deploys a function to the cloud', (yargs0) => {
|
61 | yargs0
|
62 | .usage('Usage: $0 deploy <function> [options]')
|
63 | .positional('function', {
|
64 | describe: 'Function name',
|
65 | type: 'string',
|
66 | });
|
67 | }, async (argv) => {
|
68 | await handleCommand(argv, deployHandler);
|
69 | })
|
70 | .command('remove <function> [options]', 'Remove a previously deployed function', (yargs0) => {
|
71 | yargs0
|
72 | .usage('Usage: $0 remove <function> [options]')
|
73 | .positional('function', {
|
74 | describe: 'Function name',
|
75 | type: 'string',
|
76 | });
|
77 | }, async (argv) => {
|
78 | await handleCommand(argv, removeHandler);
|
79 | })
|
80 | .command('invoke <function> [options]', 'Invoke a Binaris function', (yargs0) => {
|
81 | yargs0
|
82 | .usage('Usage: $0 invoke <function> [options]')
|
83 | .positional('function', {
|
84 | describe: 'Function name',
|
85 | type: 'string',
|
86 | })
|
87 | .option('json', {
|
88 | alias: 'j',
|
89 | describe: 'Path to file containing JSON data',
|
90 | type: 'string',
|
91 | })
|
92 | .option('data', {
|
93 | alias: 'd',
|
94 | describe: 'Data to send with invocation',
|
95 | type: 'string',
|
96 | })
|
97 | .example(
|
98 | ` // invoke a function
|
99 | bn invoke foo
|
100 |
|
101 | // invoke using JSON file data
|
102 | bn invoke foo --json ./path/to/myfile.json
|
103 |
|
104 | // invoke foo and send JSON data in the body
|
105 | bn invoke foo --data '{ "name": "helloworld" }'`);
|
106 | }, async (argv) => {
|
107 | await handleCommand(argv, invokeHandler);
|
108 | })
|
109 | .command('list [options]', 'List all deployed functions', (yargs0) => {
|
110 | yargs0
|
111 | .usage('Usage: $0 list [options]')
|
112 | .option('json', { describe: 'Output as JSON' });
|
113 | }, async (argv) => {
|
114 | await handleCommand(argv, listHandler);
|
115 | })
|
116 | .command('perf <function> [options]', 'Measure invocation latency (experimental)', (yargs0) => {
|
117 | yargs0
|
118 | .usage('Usage: $0 perf <function> [options]')
|
119 | .positional('function', {
|
120 | describe: 'Function name',
|
121 | type: 'string',
|
122 | })
|
123 | .option('maxRequests', {
|
124 | alias: 'n',
|
125 | describe: 'Number of invocations to perform',
|
126 | type: 'number',
|
127 | default: 5000,
|
128 | })
|
129 | .option('concurrency', {
|
130 | alias: 'c',
|
131 | describe: 'How many requests run concurrently',
|
132 | type: 'number',
|
133 | default: 1,
|
134 | })
|
135 | .example(
|
136 | ` // Run performance test on function foo (100 invocations, serially)
|
137 | bn perf foo
|
138 |
|
139 | // Run performance test with 1,000 invocations
|
140 | bn perf foo -n 1000
|
141 |
|
142 | // Run performance test with 1,000 invocations and 4 concurrent connections
|
143 | bn perf foo -n 1000 -c 4
|
144 | `);
|
145 | }, async (argv) => {
|
146 | await handleCommand(argv, perfHandler);
|
147 | })
|
148 | .command('logs <function> [options]', 'Print the logs of a function', (yargs0) => {
|
149 | yargs0
|
150 | .usage('Usage: $0 logs <function> [options]')
|
151 | .positional('function', {
|
152 | describe: 'Function name',
|
153 | type: 'string',
|
154 | })
|
155 | .option('tail', {
|
156 | alias: 't',
|
157 | describe: 'Outputs logs in "tail -f" fashion',
|
158 | type: 'boolean',
|
159 | })
|
160 | .option('since', {
|
161 | alias: 's',
|
162 | describe: 'Outputs logs after the given ISO timestamp',
|
163 | type: 'string',
|
164 | })
|
165 | .example(
|
166 | ` // retrieve all logs
|
167 | bn logs foo
|
168 |
|
169 | // tail all logs
|
170 | bn logs foo --tail
|
171 |
|
172 | // ISO
|
173 | bn logs foo --since 2018-03-09T22:12:21.861Z
|
174 |
|
175 | // unix
|
176 | bn logs foo --since 1520816105798
|
177 |
|
178 | // offset format
|
179 | bn logs foo --since 3d
|
180 | bn logs foo --since 13hours
|
181 | bn logs foo --since 9s`);
|
182 | }, async (argv) => {
|
183 | if (argv.since) {
|
184 | try {
|
185 |
|
186 | argv.since = parseTimeString(argv.since);
|
187 | } catch (err) {
|
188 | msgAndExit(err.message);
|
189 | }
|
190 | }
|
191 | await handleCommand(argv, logsHandler);
|
192 | })
|
193 | .command('login', 'Login to your Binaris account using an API key', (yargs0) => {
|
194 | yargs0
|
195 | .usage('Usage: $0 login');
|
196 | }, async () => {
|
197 | await loginHandler();
|
198 | })
|
199 |
|
200 | .demand(1, 'Please provide at least 1 valid command')
|
201 | .help('help')
|
202 | .alias('help', 'h')
|
203 | .wrap(null);
|
204 |
|
205 | const commands = yargs.getCommandInstance().getCommands();
|
206 |
|
207 | const currCommand = yargs.argv._[0];
|
208 |
|
209 | if (currCommand && commands.indexOf(currCommand) === -1) {
|
210 | msgAndExit(`Unknown command: '${currCommand}'`, true);
|
211 | }
|
212 |
|