Skip to content

Commit

Permalink
Switch to yargs.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdobry committed Aug 28, 2016
1 parent f3733e8 commit 563013b
Show file tree
Hide file tree
Showing 30 changed files with 566 additions and 438 deletions.
27 changes: 27 additions & 0 deletions bigquery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ analytics data warehouse.
* [Samples](#samples)
* [Create A Simple Application With the API](#create-a-simple-application-with-the-api)
* [Datasets](#datasets)
* [Queries](#queries)
* [Tables](#tables)

## Setup
Expand Down Expand Up @@ -72,6 +73,32 @@ For more information, see https://cloud.google.com/bigquery/docs
[datasets_docs]: https://cloud.google.com/bigquery/docs
[datasets_code]: datasets.js

### Queries

View the [documentation][queries_docs] or the [source code][queries_code].

__Usage:__ `node queries --help`

```
Commands:
sync <query> Run a synchronous query.
async <query> Start an asynchronous query.
poll <jobId> Get the status of a job.
Options:
--help Show help [boolean]
Examples:
node queries sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"
node queries async "SELECT * FROM publicdata:samples.natality LIMIT 5;"
node queries poll 12345
For more information, see https://cloud.google.com/bigquery/docs
```

[queries_docs]: https://cloud.google.com/bigquery/docs
[queries_code]: queries.js

### Tables

View the [documentation][tables_docs] or the [source code][tables_code].
Expand Down
66 changes: 28 additions & 38 deletions bigquery/query.js → bigquery/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// [START complete]
// [START all]
/**
* Command-line application to perform an synchronous query in BigQuery.
*
Expand Down Expand Up @@ -127,51 +127,41 @@ function asyncPoll (jobId, callback) {
});
}
// [END async_query]
// [END all]

// [START usage]
function printUsage () {
console.log('Usage:');
console.log('\nCommands:\n');
console.log('\tnode query sync QUERY');
console.log('\tnode query async QUERY');
console.log('\tnode query poll JOB_ID');
console.log('\nExamples:\n');
console.log('\tnode query sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"');
console.log('\tnode query async "SELECT * FROM publicdata:samples.natality LIMIT 5;"');
console.log('\tnode query poll 12345');
}
// [END usage]

// The command-line program:
var program = {
// Print usage instructions.
printUsage: printUsage,
// The command-line program
var cli = require('yargs');
var makeHandler = require('../utils').makeHandler;

// Exports
var program = module.exports = {
asyncQuery: asyncQuery,
asyncPoll: asyncPoll,
syncQuery: syncQuery,
bigquery: bigquery,

// Run the sample.
main: function (args, cb) {
var command = args.shift();
var arg = args.shift();
if (command === 'sync') {
this.syncQuery(arg, cb);
} else if (command === 'async') {
this.asyncQuery(arg, cb);
} else if (command === 'poll') {
this.asyncPoll(arg, cb);
} else {
this.printUsage();
}
main: function (args) {
// Run the command-line program
cli.help().strict().parse(args).argv;
}
};

cli
.demand(1)
.command('sync <query>', 'Run a synchronous query.', {}, function (options) {
program.syncQuery(options.query, makeHandler());
})
.command('async <query>', 'Start an asynchronous query.', {}, function (options) {
program.asyncQuery(options.query, makeHandler());
})
.command('poll <jobId>', 'Get the status of a job.', {}, function (options) {
program.asyncPoll(options.jobId, makeHandler());
})
.example('node $0 sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"')
.example('node $0 async "SELECT * FROM publicdata:samples.natality LIMIT 5;"')
.example('node $0 poll 12345')
.wrap(80)
.recommendCommands()
.epilogue('For more information, see https://cloud.google.com/bigquery/docs');

if (module === require.main) {
program.main(process.argv.slice(2), console.log);
program.main(process.argv.slice(2));
}
// [END complete]

module.exports = program;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

'use strict';

var example = require('../query');
var example = require('../queries');

describe('bigquery:query', function () {
describe('sync_query', function () {
Expand Down
85 changes: 29 additions & 56 deletions bigquery/test/query.test.js → bigquery/test/queries.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function getSample () {
var BigQueryMock = sinon.stub().returns(bigqueryMock);

return {
program: proxyquire('../query', {
program: proxyquire('../queries', {
'@google-cloud/bigquery': BigQueryMock
}),
mocks: {
Expand All @@ -58,49 +58,6 @@ function getSample () {
}

describe('bigquery:query', function () {
describe('main', function () {
it('should show usage based on arguments', function () {
var program = getSample().program;
sinon.stub(program, 'printUsage');

program.main([]);
assert(program.printUsage.calledOnce);

program.main(['-h']);
assert(program.printUsage.calledTwice);

program.main(['--help']);
assert(program.printUsage.calledThrice);
});

it('should run the correct commands', function () {
var program = getSample().program;
sinon.stub(program, 'syncQuery');
sinon.stub(program, 'asyncQuery');
sinon.stub(program, 'asyncPoll');

program.main(['sync']);
assert(program.syncQuery.calledOnce);

program.main(['async']);
assert(program.asyncQuery.calledOnce);

program.main(['poll']);
assert(program.asyncPoll.calledOnce);
});

it('should execute queries', function () {
var example = getSample();
sinon.stub(example.program, 'syncQuery');

example.program.main(['foo'], function (err, data) {
assert.ifError(err);
assert(example.program.syncQuery.calledWith({ query: 'foo' }));
assert.deepEqual(data, example.mocks.natality);
});
});
});

describe('syncQuery', function () {
var query = 'foo';

Expand Down Expand Up @@ -246,19 +203,35 @@ describe('bigquery:query', function () {
});
});

describe('printUsage', function () {
it('should print usage', function () {
describe('main', function () {
var query = 'foo';
var jobId = 'foo';

it('should call syncQuery', function () {
var program = getSample().program;
program.printUsage();
assert(console.log.calledWith('Usage:'));
assert(console.log.calledWith('\nCommands:\n'));
assert(console.log.calledWith('\tnode query sync QUERY'));
assert(console.log.calledWith('\tnode query async QUERY'));
assert(console.log.calledWith('\tnode query poll JOB_ID'));
assert(console.log.calledWith('\nExamples:\n'));
assert(console.log.calledWith('\tnode query sync "SELECT * FROM publicdata:samples.natality LIMIT 5;"'));
assert(console.log.calledWith('\tnode query async "SELECT * FROM publicdata:samples.natality LIMIT 5;"'));
assert(console.log.calledWith('\tnode query poll 12345'));

sinon.stub(program, 'syncQuery');
program.main(['sync', query]);
assert.equal(program.syncQuery.calledOnce, true);
assert.deepEqual(program.syncQuery.firstCall.args.slice(0, -1), [query]);
});

it('should call asyncQuery', function () {
var program = getSample().program;

sinon.stub(program, 'asyncQuery');
program.main(['async', query]);
assert.equal(program.asyncQuery.calledOnce, true);
assert.deepEqual(program.asyncQuery.firstCall.args.slice(0, -1), [query]);
});

it('should call asyncPoll', function () {
var program = getSample().program;

sinon.stub(program, 'asyncPoll');
program.main(['poll', jobId]);
assert.equal(program.asyncPoll.calledOnce, true);
assert.deepEqual(program.asyncPoll.firstCall.args.slice(0, -1), [jobId]);
});
});
});
11 changes: 6 additions & 5 deletions logging/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ function deleteLog (name, callback) {

// The command-line program
var cli = require('yargs');
var utils = require('../utils');

var program = module.exports = {
listLogEntries: listLogEntries,
Expand All @@ -129,7 +130,7 @@ var program = module.exports = {

cli
.demand(1)
.command('list', 'List log entries in the authenticated project.', {
.command('list', 'List log entries.', {
filter: {
alias: 'f',
type: 'string',
Expand All @@ -149,7 +150,7 @@ cli
description: 'Sort results.'
}
}, function (options) {
program.listLogEntries(options, console.log);
program.listLogEntries(utils.pick(options, ['filter', 'limit', 'sort']), utils.makeHandler());
})
.command('write <name> <resource> <entry>', 'Write a log entry.', {}, function (options) {
try {
Expand All @@ -162,12 +163,12 @@ cli
} catch (err) {
return console.error('"entry" must be a valid JSON string!');
}
program.writeLogEntry(options, console.log);
program.writeLogEntry(utils.pick(options, ['name', 'resource', 'entry']), utils.makeHandler());
})
.command('delete <name>', 'Delete a Log.', {}, function (options) {
program.deleteLog(options.name, console.log);
program.deleteLog(options.name, utils.makeHandler(false));
})
.example('node $0 list', 'List all log entires.')
.example('node $0 list', 'List all log entries.')
.example('node $0 list -f "severity = ERROR" -s "timestamp" -l 2', 'List up to 2 error entries, sorted by timestamp ascending.')
.example('node $0 write my-log \'{"type":"gae_app","labels":{"module_id":"default"}}\' \'{"message":"Hello World!"}\'', 'Write a log entry.')
.example('node $0 delete my-log', 'Delete "my-log".')
Expand Down
11 changes: 6 additions & 5 deletions logging/sinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ function deleteSink (name, callback) {

// The command-line program
var cli = require('yargs');
var utils = require('../utils');

var program = module.exports = {
createSink: createSink,
Expand Down Expand Up @@ -181,24 +182,24 @@ cli
description: 'The type of destination.'
}
}, function (options) {
program.createSink(options, console.log);
program.createSink(utils.pick(options, ['name', 'destination', 'filter', 'type']), utils.makeHandler(false));
})
.command('get <name>', 'Get the metadata for the specified sink.', {}, function (options) {
program.getSinkMetadata(options.name, console.log);
program.getSinkMetadata(options.name, utils.makeHandler());
})
.command('list', 'List all sinks in the authenticated project.', {}, function () {
program.listSinks(console.log);
program.listSinks(utils.makeHandler(true, 'id'));
})
.command('update <name> <metadata>', 'Update the metadata for the specified sink.', {}, function (options) {
try {
options.metadata = JSON.parse(options.metadata);
} catch (err) {
return console.error('"metadata" must be a valid JSON string!');
}
program.updateSink(options, console.log);
program.updateSink(utils.pick(options, ['name', 'metadata']), utils.makeHandler(false));
})
.command('delete <name>', 'Delete the specified sink.', {}, function (options) {
program.deleteSink(options.name, console.log);
program.deleteSink(options.name, utils.makeHandler(false));
})
.example('node $0 create my-sink my-bucket --type bucket', 'Create a new sink named "my-sink" that exports logs to a Cloud Storage bucket.')
.example('node $0 create my-sink my-dataset --type dataset', 'Create a new sink named "my-sink" that exports logs to a BigQuery dataset.')
Expand Down
22 changes: 17 additions & 5 deletions logging/test/logs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,25 @@ describe('logging:entries', function () {

sinon.stub(program, 'listLogEntries');
program.main(['list', '-f', '"' + filter + '"', '-l', 1, '-s', 'field']);
assert(program.listLogEntries.calledOnce);
assert.equal(program.listLogEntries.calledOnce, true);
assert.deepEqual(program.listLogEntries.firstCall.args.slice(0, -1), [{
filter: '"' + filter + '"',
limit: 1,
sort: 'field'
}]);
});

it('should call writeLogEntry', function () {
var program = getSample().program;

sinon.stub(program, 'writeLogEntry');
program.main(['write', logName, '{}', '{}']);
assert.equal(program.writeLogEntry.callCount, 1);
assert.equal(program.writeLogEntry.calledOnce, true);
assert.deepEqual(program.writeLogEntry.firstCall.args.slice(0, -1), [{
name: logName,
resource: {},
entry: {}
}]);
});

it('should validate args and call writeLogEntry', function () {
Expand All @@ -174,16 +184,18 @@ describe('logging:entries', function () {
sinon.stub(program, 'writeLogEntry');
program.main(['write', logName, '"{"invalid', '"{"invalid']);
assert.equal(program.writeLogEntry.called, false, 'writeLogEntry should not have been called');
assert(console.error.calledWith('"resource" must be a valid JSON string!'));
assert(console.error.calledWith('"entry" must be a valid JSON string!'));
assert.equal(console.error.calledTwice, true);
assert.deepEqual(console.error.firstCall.args, ['"resource" must be a valid JSON string!']);
assert.deepEqual(console.error.secondCall.args, ['"entry" must be a valid JSON string!']);
});

it('should call deleteLog', function () {
var program = getSample().program;

sinon.stub(program, 'deleteLog');
program.main(['delete', logName]);
assert(program.deleteLog.calledOnce);
assert.equal(program.deleteLog.calledOnce, true);
assert.deepEqual(program.deleteLog.firstCall.args.slice(0, -1), [logName]);
});
});
});
Loading

0 comments on commit 563013b

Please sign in to comment.