From 563013b8a0164af6238da5844cefba75e775db35 Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Thu, 25 Aug 2016 21:46:26 -0700 Subject: [PATCH] Switch to yargs. --- bigquery/README.md | 27 ++++ bigquery/{query.js => queries.js} | 66 +++++----- .../{query.test.js => queries.test.js} | 2 +- .../test/{query.test.js => queries.test.js} | 85 +++++-------- logging/logs.js | 11 +- logging/sinks.js | 11 +- logging/test/logs.test.js | 22 +++- logging/test/sinks.test.js | 30 +++-- pubsub/README.md | 45 +++---- pubsub/package.json | 3 +- pubsub/subscriptions.js | 76 ++++++------ pubsub/system-test/subscriptions.test.js | 18 +-- pubsub/system-test/topics.test.js | 16 +-- pubsub/test/subscriptions.test.js | 94 +++++++------- pubsub/test/topics.test.js | 82 ++++++------ pubsub/topics.js | 75 ++++++----- resource/test/projects.test.js | 3 +- storage/acl.js | 7 +- storage/buckets.js | 7 +- storage/encryption.js | 7 +- storage/files.js | 19 +-- storage/test/acl.test.js | 25 +++- storage/test/buckets.test.js | 13 +- storage/test/encryption.test.js | 22 +++- storage/test/files.test.js | 117 ++++++++++++------ storage/test/transfer.test.js | 52 ++++++-- storage/transfer.js | 31 ++--- translate/system-test/translate.test.js | 4 +- translate/test/translate.test.js | 18 ++- translate/translate.js | 16 ++- 30 files changed, 566 insertions(+), 438 deletions(-) rename bigquery/{query.js => queries.js} (78%) rename bigquery/system-test/{query.test.js => queries.test.js} (98%) rename bigquery/test/{query.test.js => queries.test.js} (79%) diff --git a/bigquery/README.md b/bigquery/README.md index 2882fe6f3d..0192714938 100644 --- a/bigquery/README.md +++ b/bigquery/README.md @@ -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 @@ -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 Run a synchronous query. + async Start an asynchronous query. + poll 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]. diff --git a/bigquery/query.js b/bigquery/queries.js similarity index 78% rename from bigquery/query.js rename to bigquery/queries.js index ceabb5bda5..c2750bc03f 100644 --- a/bigquery/query.js +++ b/bigquery/queries.js @@ -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. * @@ -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 ', 'Run a synchronous query.', {}, function (options) { + program.syncQuery(options.query, makeHandler()); + }) + .command('async ', 'Start an asynchronous query.', {}, function (options) { + program.asyncQuery(options.query, makeHandler()); + }) + .command('poll ', '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; diff --git a/bigquery/system-test/query.test.js b/bigquery/system-test/queries.test.js similarity index 98% rename from bigquery/system-test/query.test.js rename to bigquery/system-test/queries.test.js index a680565e4c..dff2faf770 100644 --- a/bigquery/system-test/query.test.js +++ b/bigquery/system-test/queries.test.js @@ -13,7 +13,7 @@ 'use strict'; -var example = require('../query'); +var example = require('../queries'); describe('bigquery:query', function () { describe('sync_query', function () { diff --git a/bigquery/test/query.test.js b/bigquery/test/queries.test.js similarity index 79% rename from bigquery/test/query.test.js rename to bigquery/test/queries.test.js index 7f801d35ed..6d9241365f 100644 --- a/bigquery/test/query.test.js +++ b/bigquery/test/queries.test.js @@ -43,7 +43,7 @@ function getSample () { var BigQueryMock = sinon.stub().returns(bigqueryMock); return { - program: proxyquire('../query', { + program: proxyquire('../queries', { '@google-cloud/bigquery': BigQueryMock }), mocks: { @@ -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'; @@ -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]); }); }); }); diff --git a/logging/logs.js b/logging/logs.js index 2629071056..1fded8498d 100644 --- a/logging/logs.js +++ b/logging/logs.js @@ -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, @@ -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', @@ -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 ', 'Write a log entry.', {}, function (options) { try { @@ -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 ', '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".') diff --git a/logging/sinks.js b/logging/sinks.js index a6f3540d4e..f739f3edec 100644 --- a/logging/sinks.js +++ b/logging/sinks.js @@ -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, @@ -181,13 +182,13 @@ 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 ', '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 ', 'Update the metadata for the specified sink.', {}, function (options) { try { @@ -195,10 +196,10 @@ cli } 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 ', '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.') diff --git a/logging/test/logs.test.js b/logging/test/logs.test.js index 2d7ceffa7d..535aed1731 100644 --- a/logging/test/logs.test.js +++ b/logging/test/logs.test.js @@ -157,7 +157,12 @@ 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 () { @@ -165,7 +170,12 @@ describe('logging:entries', function () { 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 () { @@ -174,8 +184,9 @@ 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 () { @@ -183,7 +194,8 @@ describe('logging:entries', function () { 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]); }); }); }); diff --git a/logging/test/sinks.test.js b/logging/test/sinks.test.js index 6c5cec954c..5c404f065b 100644 --- a/logging/test/sinks.test.js +++ b/logging/test/sinks.test.js @@ -298,7 +298,13 @@ describe('logging:sinks', function () { sinon.stub(program, 'createSink'); program.main(['create', sinkName, bucketName, '-t', 'bucket']); - assert(program.createSink.calledOnce); + assert.equal(program.createSink.calledOnce, true); + assert.deepEqual(program.createSink.firstCall.args.slice(0, -1), [{ + name: sinkName, + destination: bucketName, + type: 'bucket', + filter: undefined + }]); }); it('should call getSinkMetadata', function () { @@ -306,7 +312,8 @@ describe('logging:sinks', function () { sinon.stub(program, 'getSinkMetadata'); program.main(['get', sinkName]); - assert(program.getSinkMetadata.calledOnce); + assert.equal(program.getSinkMetadata.calledOnce, true); + assert.deepEqual(program.getSinkMetadata.firstCall.args.slice(0, -1), [sinkName]); }); it('should call listSinks', function () { @@ -314,15 +321,20 @@ describe('logging:sinks', function () { sinon.stub(program, 'listSinks'); program.main(['list']); - assert(program.listSinks.calledOnce); + assert.equal(program.listSinks.calledOnce, true); + assert.deepEqual(program.listSinks.firstCall.args.slice(0, -1), []); }); it('should call updateSink', function () { var program = getSample().program; sinon.stub(program, 'updateSink'); - program.main(['update', sinkName, '"{}"']); - assert(program.updateSink.calledOnce); + program.main(['update', sinkName, '{}']); + assert.equal(program.updateSink.calledOnce, true); + assert.deepEqual(program.updateSink.firstCall.args.slice(0, -1), [{ + name: sinkName, + metadata: {} + }]); }); it('should validate metadata and call updateSink', function () { @@ -330,8 +342,9 @@ describe('logging:sinks', function () { sinon.stub(program, 'updateSink'); program.main(['update', sinkName, '"{"invalid']); - assert.equal(program.updateSink.called, false, 'updateSink should not have been called'); - assert(console.error.calledWith('"metadata" must be a valid JSON string!')); + assert.equal(program.updateSink.called, false); + assert.equal(console.error.calledOnce, true); + assert.deepEqual(console.error.firstCall.args, ['"metadata" must be a valid JSON string!']); }); it('should call deleteSink', function () { @@ -339,7 +352,8 @@ describe('logging:sinks', function () { sinon.stub(program, 'deleteSink'); program.main(['delete', sinkName]); - assert(program.deleteSink.calledOnce); + assert.equal(program.deleteSink.calledOnce, true); + assert.deepEqual(program.deleteSink.firstCall.args.slice(0, -1), [sinkName]); }); }); }); diff --git a/pubsub/README.md b/pubsub/README.md index 05b0f80373..a4c6d6e925 100644 --- a/pubsub/README.md +++ b/pubsub/README.md @@ -34,21 +34,23 @@ View the [documentation][topics_docs] or the [source code][topics_code]. __Usage:__ `node topics --help` ``` -Usage: node topics COMMAND [ARGS...] - Commands: + create Create a new topic. + list List topics. + publish Publish a message to the specified topic. + delete Delete the specified topic. - create TOPIC_NAME - delete TOPIC_NAME - publish TOPIC_NAME MESSAGE - list +Options: + --help Show help [boolean] Examples: + node topics create my-topic Create a new topic named "my-topic". + node topics list List topics. + node topics publish my-topic Publish a message to "my-topic". + '{"data":"Hello world!"}' + node topics delete my-topic Delete a topic named "my-topic". - node topics create my-topic - node topics list - node topics publish my-topic '{"data":"Hello world!"}' - node topics delete my-topic +For more information, see https://cloud.google.com/pubsub/docs ``` [topics_docs]: https://cloud.google.com/pubsub/publisher @@ -61,22 +63,23 @@ View the [documentation][subscriptions_docs] or the [source code][subscriptions_ __Usage:__ `node subscriptions --help` ``` -Usage: node subscriptions COMMAND [ARGS...] - Commands: + create Create a new subscription. + list [topic] List subscriptions. + pull Pull messages from the specified subscription. + delete Delete the specified subscription. - create TOPIC_NAME SUBSCRIPTION_NAME - delete SUBSCRIPTION_NAME - pull SUBSCRIPTION_NAME - list [TOPIC_NAME] +Options: + --help Show help [boolean] Examples: + node subscriptions create my-topic my-subscription Create a new subscription. + node subscriptions delete my-subscription Delete a subscription. + node subscriptions pull my-subscription Pull messages from "my-subscription". + node subscriptions list List all subscriptions. + node subscriptions list my-topic List subscriptions to topic "my-topic". - node subscriptions create my-topic my-subscription - node subscriptions delete my-subscription - node subscriptions pull my-subscription - node subscriptions list - node subscriptions list my-topic +For more information, see https://cloud.google.com/pubsub/docs ``` [subscriptions_docs]: https://cloud.google.com/pubsub/subscriber diff --git a/pubsub/package.json b/pubsub/package.json index a741fc1281..3c40d08300 100644 --- a/pubsub/package.json +++ b/pubsub/package.json @@ -9,7 +9,8 @@ "system-test": "mocha -R spec -t 120000 --require intelli-espower-loader ../system-test/_setup.js system-test/*.test.js" }, "dependencies": { - "@google-cloud/pubsub": "^0.1.1" + "@google-cloud/pubsub": "^0.1.1", + "yargs": "^5.0.0" }, "devDependencies": { "mocha": "^3.0.2", diff --git a/pubsub/subscriptions.js b/pubsub/subscriptions.js index f36b37c571..42c883d8d6 100644 --- a/pubsub/subscriptions.js +++ b/pubsub/subscriptions.js @@ -157,50 +157,44 @@ function pullMessages (subscriptionName, callback) { } // [END pull_messages] -// [START usage] -function printUsage () { - console.log('Usage: node subscriptions COMMAND [ARGS...]'); - console.log('\nCommands:\n'); - console.log('\tcreate TOPIC_NAME SUBSCRIPTION_NAME'); - console.log('\tdelete SUBSCRIPTION_NAME'); - console.log('\tpull SUBSCRIPTION_NAME'); - console.log('\tlist [TOPIC_NAME]'); - console.log('\nExamples:\n'); - console.log('\tnode subscriptions create my-topic my-subscription'); - console.log('\tnode subscriptions delete my-subscription'); - console.log('\tnode subscriptions pull my-subscription'); - console.log('\tnode subscriptions list'); - console.log('\tnode subscriptions list my-topic'); -} -// [END usage] - // The command-line program -var program = { - create: createSubscription, - delete: deleteSubscription, - pull: pullMessages, - list: listSubscriptions, - printUsage: printUsage, - - // Executed when this program is run from the command-line - main: function (args, cb) { - var command = args.shift(); - if (command === 'create') { - this.create(args[0], args[1], cb); - } else if (command === 'delete') { - this.delete(args[0], cb); - } else if (command === 'pull') { - this.pull(args[0], cb); - } else if (command === 'list') { - this.list(args[0], cb); - } else { - this.printUsage(); - } +var cli = require('yargs'); +var makeHandler = require('../utils').makeHandler; + +var program = module.exports = { + createSubscription: createSubscription, + deleteSubscription: deleteSubscription, + pullMessages: pullMessages, + listSubscriptions: listSubscriptions, + main: function (args) { + // Run the command-line program + cli.help().strict().parse(args).argv; } }; +cli + .demand(1) + .command('create ', 'Create a new subscription.', {}, function (options) { + program.createSubscription(options.topic, options.name, makeHandler(true, 'id')); + }) + .command('list [topic]', 'List subscriptions.', {}, function (options) { + program.listSubscriptions(options.topic, makeHandler(true, 'id')); + }) + .command('pull ', 'Pull messages from the specified subscription.', {}, function (options) { + program.pullMessages(options.subscription, makeHandler(false)); + }) + .command('delete ', 'Delete the specified subscription.', {}, function (options) { + program.deleteSubscription(options.subscription, makeHandler(false)); + }) + .example('node $0 create my-topic my-subscription', 'Create a new subscription.') + .example('node $0 delete my-subscription', 'Delete a subscription.') + .example('node $0 pull my-subscription', 'Pull messages from "my-subscription".') + .example('node $0 list', 'List all subscriptions.') + .example('node $0 list my-topic', 'List subscriptions to topic "my-topic".') + .wrap(100) + .recommendCommands() + .epilogue('For more information, see https://cloud.google.com/pubsub/docs'); + if (module === require.main) { - program.main(process.argv.slice(2), console.log); + program.main(process.argv.slice(2)); } - -module.exports = program; diff --git a/pubsub/system-test/subscriptions.test.js b/pubsub/system-test/subscriptions.test.js index 64cc699d33..d19aceab75 100644 --- a/pubsub/system-test/subscriptions.test.js +++ b/pubsub/system-test/subscriptions.test.js @@ -33,9 +33,9 @@ describe('pubsub:subscriptions', function () { pubsub.topic(topicName).delete(done); }); - describe('create', function () { + describe('createSubscription', function () { it('should create a subscription', function (done) { - program.create(topicName, subscriptionName, function (err, subscription) { + program.createSubscription(topicName, subscriptionName, function (err, subscription) { assert.ifError(err); assert.equal(subscription.name, name); assert(console.log.calledWith('Created subscription %s to topic %s', subscriptionName, topicName)); @@ -45,9 +45,9 @@ describe('pubsub:subscriptions', function () { }); }); - describe('list', function () { + describe('listSubscriptions', function () { it('should list subscriptions', function (done) { - program.list(topicName, function (err, subscriptions) { + program.listSubscriptions(topicName, function (err, subscriptions) { assert.ifError(err); assert(Array.isArray(subscriptions)); assert(subscriptions.length > 0); @@ -57,7 +57,7 @@ describe('pubsub:subscriptions', function () { assert.equal(recentlyCreatedSubscriptions.length, 1, 'list has newly created subscription'); assert(console.log.calledWith('Found %d subscriptions!', subscriptions.length)); - program.list(undefined, function (err, allSubscriptions) { + program.listSubscriptions(undefined, function (err, allSubscriptions) { assert.ifError(err); assert(Array.isArray(allSubscriptions)); assert(allSubscriptions.length > 0); @@ -72,7 +72,7 @@ describe('pubsub:subscriptions', function () { }); }); - describe('pull', function () { + describe('pullMessages', function () { var expected = 'Hello World!'; before(function (done) { @@ -80,7 +80,7 @@ describe('pubsub:subscriptions', function () { }); it('should pull messages', function (done) { - program.pull(subscriptionName, function (err, messages) { + program.pullMessages(subscriptionName, function (err, messages) { assert.ifError(err); assert(Array.isArray(messages)); assert(messages.length > 0); @@ -92,9 +92,9 @@ describe('pubsub:subscriptions', function () { }); }); - describe('delete', function () { + describe('deleteSubscription', function () { it('should delete a subscription', function (done) { - program.delete(subscriptionName, function (err) { + program.deleteSubscription(subscriptionName, function (err) { assert.ifError(err); assert(console.log.calledWith('Deleted subscription: %s', subscriptionName)); done(); diff --git a/pubsub/system-test/topics.test.js b/pubsub/system-test/topics.test.js index fc178fb3f4..62704a4440 100644 --- a/pubsub/system-test/topics.test.js +++ b/pubsub/system-test/topics.test.js @@ -20,9 +20,9 @@ var projectId = process.env.GCLOUD_PROJECT; var name = 'projects/' + projectId + '/topics/' + topicName; describe('pubsub:topics', function () { - describe('create', function () { + describe('createTopic', function () { it('should create a topic', function (done) { - program.create(topicName, function (err, topic) { + program.createTopic(topicName, function (err, topic) { assert.ifError(err); assert.equal(topic.name, name); assert(console.log.calledWith('Created topic: %s', topicName)); @@ -31,9 +31,9 @@ describe('pubsub:topics', function () { }); }); - describe('list', function () { + describe('listTopics', function () { it('should list topics', function (done) { - program.list(function (err, topics) { + program.listTopics(function (err, topics) { assert.ifError(err); assert(Array.isArray(topics)); assert(topics.length > 0); @@ -47,10 +47,10 @@ describe('pubsub:topics', function () { }); }); - describe('publish', function () { + describe('publishMessage', function () { it('should publish a message', function (done) { var json = '{"data":"Hello World!"}'; - program.publish(topicName, json, function (err, messageIds) { + program.publishMessage(topicName, json, function (err, messageIds) { assert.ifError(err); assert(Array.isArray(messageIds)); assert(messageIds.length > 0); @@ -60,9 +60,9 @@ describe('pubsub:topics', function () { }); }); - describe('delete', function () { + describe('deleteTopic', function () { it('should delete a topic', function (done) { - program.delete(topicName, function (err) { + program.deleteTopic(topicName, function (err) { assert.ifError(err); assert(console.log.calledWith('Deleted topic: %s', topicName)); done(); diff --git a/pubsub/test/subscriptions.test.js b/pubsub/test/subscriptions.test.js index 5dbbe73c3a..103030c84e 100644 --- a/pubsub/test/subscriptions.test.js +++ b/pubsub/test/subscriptions.test.js @@ -67,7 +67,7 @@ describe('pubsub:subscriptions', function () { describe('create', function () { it('should create a subscription', function () { var sample = getSample(); - sample.program.create(topicName, subscriptionName, function (err, subscription) { + sample.program.createSubscription(topicName, subscriptionName, function (err, subscription) { assert.ifError(err); assert.strictEqual(subscription, sample.mocks.subscription); assert(console.log.calledWith('Created subscription %s to topic %s', subscriptionName, topicName)); @@ -75,7 +75,7 @@ describe('pubsub:subscriptions', function () { }); it('should require topicName', function () { var sample = getSample(); - sample.program.create(undefined, undefined, function (err, subscription) { + sample.program.createSubscription(undefined, undefined, function (err, subscription) { assert(err); assert(err.message = '"topicName" is required!'); assert.equal(subscription, undefined); @@ -83,7 +83,7 @@ describe('pubsub:subscriptions', function () { }); it('should require subscriptionName', function () { var sample = getSample(); - sample.program.create(topicName, undefined, function (err, subscription) { + sample.program.createSubscription(topicName, undefined, function (err, subscription) { assert(err); assert(err.message = '"subscriptionName" is required!'); assert.equal(subscription, undefined); @@ -93,7 +93,7 @@ describe('pubsub:subscriptions', function () { var sample = getSample(); var error = 'error'; sample.mocks.pubsub.subscribe.callsArgWith(3, new Error(error)); - sample.program.create(topicName, subscriptionName, function (err) { + sample.program.createSubscription(topicName, subscriptionName, function (err) { assert(err); assert(err.message === 'error'); }); @@ -103,14 +103,14 @@ describe('pubsub:subscriptions', function () { describe('delete', function () { it('should delete a subscription', function () { var sample = getSample(); - sample.program.delete(subscriptionName, function (err) { + sample.program.deleteSubscription(subscriptionName, function (err) { assert.ifError(err); assert(console.log.calledWith('Deleted subscription: %s', subscriptionName)); }); }); it('should require subscriptionName', function () { var sample = getSample(); - sample.program.delete(undefined, function (err, subscription) { + sample.program.deleteSubscription(undefined, function (err, subscription) { assert(err); assert(err.message = '"subscriptionName" is required!'); assert.equal(subscription, undefined); @@ -120,7 +120,7 @@ describe('pubsub:subscriptions', function () { var sample = getSample(); var error = 'error'; sample.mocks.subscription.delete.callsArgWith(0, new Error(error)); - sample.program.delete(subscriptionName, function (err) { + sample.program.deleteSubscription(subscriptionName, function (err) { assert(err); assert(err.message === 'error'); }); @@ -130,7 +130,7 @@ describe('pubsub:subscriptions', function () { describe('list', function () { it('should list all subscriptions', function () { var sample = getSample(); - sample.program.list(undefined, function (err, subscriptions) { + sample.program.listSubscriptions(undefined, function (err, subscriptions) { assert.ifError(err); assert.strictEqual(subscriptions, sample.mocks.subscriptions); assert(console.log.calledWith('Found %d subscriptions!', subscriptions.length)); @@ -138,7 +138,7 @@ describe('pubsub:subscriptions', function () { }); it('should list all subscriptions of a topic', function () { var sample = getSample(); - sample.program.list(topicName, function (err, subscriptions) { + sample.program.listSubscriptions(topicName, function (err, subscriptions) { assert.ifError(err); assert.strictEqual(subscriptions, sample.mocks.subscriptions); assert(console.log.calledWith('Found %d subscriptions!', subscriptions.length)); @@ -148,7 +148,7 @@ describe('pubsub:subscriptions', function () { var sample = getSample(); var error = 'error'; sample.mocks.pubsub.getSubscriptions.callsArgWith(1, new Error(error)); - sample.program.list(undefined, function (err, subscriptions) { + sample.program.listSubscriptions(undefined, function (err, subscriptions) { assert(err); assert(err.message === 'error'); assert.equal(subscriptions, undefined); @@ -159,7 +159,7 @@ describe('pubsub:subscriptions', function () { describe('pull', function () { it('should pull messages', function () { var sample = getSample(); - sample.program.pull(subscriptionName, function (err, messages) { + sample.program.pullMessages(subscriptionName, function (err, messages) { assert.ifError(err); assert.strictEqual(messages, sample.mocks.messages); assert(console.log.calledWith('Pulled %d messages!', messages.length)); @@ -168,7 +168,7 @@ describe('pubsub:subscriptions', function () { }); it('should require subscriptionName', function () { var sample = getSample(); - sample.program.pull(undefined, function (err, subscription) { + sample.program.pullMessages(undefined, function (err, subscription) { assert(err); assert(err.message = '"subscriptionName" is required!'); assert.equal(subscription, undefined); @@ -178,7 +178,7 @@ describe('pubsub:subscriptions', function () { var sample = getSample(); var error = 'error'; sample.mocks.subscription.pull.callsArgWith(1, new Error(error)); - sample.program.pull(subscriptionName, function (err, messages) { + sample.program.pullMessages(subscriptionName, function (err, messages) { assert(err); assert(err.message === 'error'); assert.equal(messages, undefined); @@ -188,57 +188,57 @@ describe('pubsub:subscriptions', function () { var sample = getSample(); var error = 'error'; sample.mocks.subscription.ack.callsArgWith(1, new Error(error)); - sample.program.pull(subscriptionName, function (err) { + sample.program.pullMessages(subscriptionName, function (err) { assert(err); assert(err.message === 'error'); }); }); }); - describe('printUsage', function () { - it('should print usage', function () { + describe('main', function () { + it('should call createSubscription', function () { var program = getSample().program; - program.printUsage(); - - assert(console.log.calledWith('Usage: node subscriptions COMMAND [ARGS...]')); - assert(console.log.calledWith('\nCommands:\n')); - assert(console.log.calledWith('\tcreate TOPIC_NAME SUBSCRIPTION_NAME')); - assert(console.log.calledWith('\tdelete SUBSCRIPTION_NAME')); - assert(console.log.calledWith('\tpull SUBSCRIPTION_NAME')); - assert(console.log.calledWith('\tlist [TOPIC_NAME]')); - assert(console.log.calledWith('\nExamples:\n')); - assert(console.log.calledWith('\tnode subscriptions create my-topic my-subscription')); - assert(console.log.calledWith('\tnode subscriptions delete my-subscription')); - assert(console.log.calledWith('\tnode subscriptions pull my-subscription')); - assert(console.log.calledWith('\tnode subscriptions list')); - assert(console.log.calledWith('\tnode subscriptions list my-topic')); + sinon.stub(program, 'createSubscription'); + program.main(['create', topicName, subscriptionName]); + assert.equal(program.createSubscription.calledOnce, true); + assert.deepEqual(program.createSubscription.firstCall.args.slice(0, -1), [topicName, subscriptionName]); }); - }); - describe('main', function () { - it('should call the right commands', function () { + it('should call deleteSubscription', function () { var program = getSample().program; - sinon.stub(program, 'create'); - program.main(['create']); - assert(program.create.calledOnce); + sinon.stub(program, 'deleteSubscription'); + program.main(['delete', subscriptionName]); + assert.equal(program.deleteSubscription.calledOnce, true); + assert.deepEqual(program.deleteSubscription.firstCall.args.slice(0, -1), [subscriptionName]); + }); - sinon.stub(program, 'delete'); - program.main(['delete']); - assert(program.delete.calledOnce); + it('should call listSubscriptions', function () { + var program = getSample().program; + sinon.stub(program, 'listSubscriptions'); - sinon.stub(program, 'list'); program.main(['list']); - assert(program.list.calledOnce); + assert.equal(program.listSubscriptions.calledOnce, true); + assert.deepEqual(program.listSubscriptions.firstCall.args.slice(0, -1), [undefined]); + }); - sinon.stub(program, 'pull'); - program.main(['pull']); - assert(program.pull.calledOnce); + it('should call listSubscriptions and filter by topic', function () { + var program = getSample().program; + sinon.stub(program, 'listSubscriptions'); + + program.main(['list', topicName]); + assert.equal(program.listSubscriptions.calledOnce, true); + assert.deepEqual(program.listSubscriptions.firstCall.args.slice(0, -1), [topicName]); + }); + + it('should call pullMessages', function () { + var program = getSample().program; - sinon.stub(program, 'printUsage'); - program.main(['--help']); - assert(program.printUsage.calledOnce); + sinon.stub(program, 'pullMessages'); + program.main(['pull', subscriptionName]); + assert.equal(program.pullMessages.calledOnce, true); + assert.deepEqual(program.pullMessages.firstCall.args.slice(0, -1), [subscriptionName]); }); }); }); diff --git a/pubsub/test/topics.test.js b/pubsub/test/topics.test.js index cddc056f60..0224bb7580 100644 --- a/pubsub/test/topics.test.js +++ b/pubsub/test/topics.test.js @@ -51,7 +51,7 @@ describe('pubsub:topics', function () { describe('create', function () { it('should create a topic', function () { var sample = getSample(); - sample.program.create(topicName, function (err, topic) { + sample.program.createTopic(topicName, function (err, topic) { assert.ifError(err); assert.strictEqual(topic, sample.mocks.topic); assert(console.log.calledWith('Created topic: %s', topicName)); @@ -59,7 +59,7 @@ describe('pubsub:topics', function () { }); it('should require name', function () { var sample = getSample(); - sample.program.create(undefined, function (err, topic) { + sample.program.createTopic(undefined, function (err, topic) { assert(err); assert(err.message = '"name" is required!'); assert.equal(topic, undefined); @@ -69,7 +69,7 @@ describe('pubsub:topics', function () { var sample = getSample(); var error = 'error'; sample.mocks.topic.get.callsArgWith(1, new Error(error)); - sample.program.create(topicName, function (err) { + sample.program.createTopic(topicName, function (err) { assert(err); assert(err.message === 'error'); }); @@ -79,14 +79,14 @@ describe('pubsub:topics', function () { describe('delete', function () { it('should delete a topic', function () { var sample = getSample(); - sample.program.delete(topicName, function (err) { + sample.program.deleteTopic(topicName, function (err) { assert.ifError(err); assert(console.log.calledWith('Deleted topic: %s', topicName)); }); }); it('should require name', function () { var sample = getSample(); - sample.program.delete(undefined, function (err, topic) { + sample.program.deleteTopic(undefined, function (err, topic) { assert(err); assert(err.message = '"name" is required!'); assert.equal(topic, undefined); @@ -96,7 +96,7 @@ describe('pubsub:topics', function () { var sample = getSample(); var error = 'error'; sample.mocks.topic.delete.callsArgWith(0, new Error(error)); - sample.program.delete(topicName, function (err) { + sample.program.deleteTopic(topicName, function (err) { assert(err); assert(err.message === 'error'); }); @@ -106,7 +106,7 @@ describe('pubsub:topics', function () { describe('publish', function () { it('should publish a message', function () { var sample = getSample(); - sample.program.publish(topicName, '{"data":"hello world"}', function (err, messageIds) { + sample.program.publishMessage(topicName, '{"data":"hello world"}', function (err, messageIds) { assert.ifError(err); assert.deepEqual(messageIds, [1]); assert(console.log.calledWith('Published %d messages!', messageIds.length)); @@ -114,7 +114,7 @@ describe('pubsub:topics', function () { }); it('should require name', function () { var sample = getSample(); - sample.program.publish(undefined, undefined, function (err, messageIds) { + sample.program.publishMessage(undefined, undefined, function (err, messageIds) { assert(err); assert(err.message = '"name" is required!'); assert.equal(messageIds, undefined); @@ -122,7 +122,7 @@ describe('pubsub:topics', function () { }); it('should require message', function () { var sample = getSample(); - sample.program.publish(topicName, undefined, function (err, messageIds) { + sample.program.publishMessage(topicName, undefined, function (err, messageIds) { assert(err); assert(err.message = '"message" is required!'); assert.equal(messageIds, undefined); @@ -130,7 +130,7 @@ describe('pubsub:topics', function () { }); it('should require a valid JSON string', function () { var sample = getSample(); - sample.program.publish(topicName, 'asdf', function (err, messageIds) { + sample.program.publishMessage(topicName, 'asdf', function (err, messageIds) { assert(err); assert(err.message = '"message" must be a valid JSON string!'); assert.equal(messageIds, undefined); @@ -140,7 +140,7 @@ describe('pubsub:topics', function () { var sample = getSample(); var error = 'error'; sample.mocks.topic.publish.callsArgWith(1, new Error(error)); - sample.program.publish(topicName, '{"data":"hello world"}', function (err, messageIds) { + sample.program.publishMessage(topicName, '{"data":"hello world"}', function (err, messageIds) { assert(err); assert(err.message === 'error'); assert.equal(messageIds, undefined); @@ -151,7 +151,7 @@ describe('pubsub:topics', function () { describe('list', function () { it('should list topics', function () { var sample = getSample(); - sample.program.list(function (err, topics) { + sample.program.listTopics(function (err, topics) { assert.ifError(err); assert.strictEqual(topics, sample.mocks.topics); assert(console.log.calledWith('Found %d topics!', topics.length)); @@ -161,7 +161,7 @@ describe('pubsub:topics', function () { var sample = getSample(); var error = 'error'; sample.mocks.pubsub.getTopics.callsArgWith(0, new Error(error)); - sample.program.list(function (err, topics) { + sample.program.listTopics(function (err, topics) { assert(err); assert(err.message === 'error'); assert.equal(topics, undefined); @@ -169,49 +169,41 @@ describe('pubsub:topics', function () { }); }); - describe('printUsage', function () { - it('should print usage', function () { + describe('main', function () { + it('should call createTopic', function () { var program = getSample().program; - program.printUsage(); - - assert(console.log.calledWith('Usage: node topics COMMAND [ARGS...]')); - assert(console.log.calledWith('\nCommands:\n')); - assert(console.log.calledWith('\tcreate TOPIC_NAME')); - assert(console.log.calledWith('\tdelete TOPIC_NAME')); - assert(console.log.calledWith('\tpublish TOPIC_NAME MESSAGE')); - assert(console.log.calledWith('\tlist')); - assert(console.log.calledWith('\nExamples:\n')); - assert(console.log.calledWith('\tnode topics create my-topic')); - assert(console.log.calledWith('\tnode topics list')); - assert(console.log.calledWith('\tnode topics publish my-topic \'{"data":"Hello world!"}\'')); - assert(console.log.calledWith('\tnode topics delete my-topic')); + sinon.stub(program, 'createTopic'); + program.main(['create', topicName]); + assert.equal(program.createTopic.calledOnce, true); + assert.deepEqual(program.createTopic.firstCall.args.slice(0, -1), [topicName]); }); - }); - describe('main', function () { - it('should call the right commands', function () { + it('should call deleteTopic', function () { var program = getSample().program; - sinon.stub(program, 'create'); - program.main(['create']); - assert(program.create.calledOnce); + sinon.stub(program, 'deleteTopic'); + program.main(['delete', topicName]); + assert.equal(program.deleteTopic.calledOnce, true); + assert.deepEqual(program.deleteTopic.firstCall.args.slice(0, -1), [topicName]); + }); - sinon.stub(program, 'delete'); - program.main(['delete']); - assert(program.delete.calledOnce); + it('should call listTopics', function () { + var program = getSample().program; - sinon.stub(program, 'list'); + sinon.stub(program, 'listTopics'); program.main(['list']); - assert(program.list.calledOnce); + assert.equal(program.listTopics.calledOnce, true); + assert.deepEqual(program.listTopics.firstCall.args.slice(0, -1), []); + }); - sinon.stub(program, 'publish'); - program.main(['publish']); - assert(program.publish.calledOnce); + it('should call publishMessage', function () { + var program = getSample().program; - sinon.stub(program, 'printUsage'); - program.main(['--help']); - assert(program.printUsage.calledOnce); + sinon.stub(program, 'publishMessage'); + program.main(['publish', topicName, '{}']); + assert.equal(program.publishMessage.calledOnce, true); + assert.deepEqual(program.publishMessage.firstCall.args.slice(0, -1), [topicName, '{}']); }); }); }); diff --git a/pubsub/topics.js b/pubsub/topics.js index 185114a03d..b60e250c83 100644 --- a/pubsub/topics.js +++ b/pubsub/topics.js @@ -132,50 +132,45 @@ function listTopics (callback) { }); } // [END list_topics] - -// [START usage] -function printUsage () { - console.log('Usage: node topics COMMAND [ARGS...]'); - console.log('\nCommands:\n'); - console.log('\tcreate TOPIC_NAME'); - console.log('\tdelete TOPIC_NAME'); - console.log('\tpublish TOPIC_NAME MESSAGE'); - console.log('\tlist'); - console.log('\nExamples:\n'); - console.log('\tnode topics create my-topic'); - console.log('\tnode topics list'); - console.log('\tnode topics publish my-topic \'{"data":"Hello world!"}\''); - console.log('\tnode topics delete my-topic'); -} -// [END usage] +// [END all] // The command-line program -var program = { - create: createTopic, - delete: deleteTopic, - publish: publishMessage, - list: listTopics, - printUsage: printUsage, - - // Executed when this program is run from the command-line - main: function (args, cb) { - var command = args.shift(); - if (command === 'create') { - this.create(args[0], cb); - } else if (command === 'delete') { - this.delete(args[0], cb); - } else if (command === 'publish') { - this.publish(args[0], args[1], cb); - } else if (command === 'list') { - this.list(cb); - } else { - this.printUsage(); - } +var cli = require('yargs'); +var makeHandler = require('../utils').makeHandler; + +var program = module.exports = { + createTopic: createTopic, + deleteTopic: deleteTopic, + publishMessage: publishMessage, + listTopics: listTopics, + main: function (args) { + // Run the command-line program + cli.help().strict().parse(args).argv; } }; +cli + .demand(1) + .command('create ', 'Create a new topic.', {}, function (options) { + program.createTopic(options.name, makeHandler(true, 'id')); + }) + .command('list', 'List topics.', {}, function (options) { + program.listTopics(makeHandler(true, 'id')); + }) + .command('publish ', 'Publish a message to the specified topic.', {}, function (options) { + program.publishMessage(options.topic, options.message, makeHandler()); + }) + .command('delete ', 'Delete the specified topic.', {}, function (options) { + program.deleteTopic(options.name, makeHandler(false)); + }) + .example('node $0 create my-topic', 'Create a new topic named "my-topic".') + .example('node $0 list', 'List topics.') + .example('node $0 publish my-topic \'{"data":"Hello world!"}\'', 'Publish a message to "my-topic".') + .example('node $0 delete my-topic', 'Delete a topic named "my-topic".') + .wrap(80) + .recommendCommands() + .epilogue('For more information, see https://cloud.google.com/pubsub/docs'); + if (module === require.main) { - program.main(process.argv.slice(2), console.log); + program.main(process.argv.slice(2)); } - -module.exports = program; diff --git a/resource/test/projects.test.js b/resource/test/projects.test.js index b0da14fe88..8706023c11 100644 --- a/resource/test/projects.test.js +++ b/resource/test/projects.test.js @@ -70,7 +70,8 @@ describe('resource:projects', function () { sinon.stub(program, 'listProjects'); program.main(['list']); - assert(program.listProjects.calledOnce); + assert.equal(program.listProjects.calledOnce, true); + assert.deepEqual(program.listProjects.firstCall.args.slice(0, -1), []); }); }); }); diff --git a/storage/acl.js b/storage/acl.js index 6ce0c15541..cd09323242 100644 --- a/storage/acl.js +++ b/storage/acl.js @@ -161,6 +161,7 @@ function deleteAccessControl (options, callback) { // The command-line program var cli = require('yargs'); +var utils = require('../utils'); var program = module.exports = { addAccessControl: addAccessControl, @@ -175,13 +176,13 @@ var program = module.exports = { cli .demand(1) .command('add ', 'Add access controls on a bucket or file.', {}, function (options) { - program.addAccessControl(options, console.log); + program.addAccessControl(utils.pick(options, ['entity', 'role', 'bucket', 'default', 'file']), utils.makeHandler()); }) .command('get [entity]', 'Get access controls on a bucket or file.', {}, function (options) { - program.getAccessControl(options, console.log); + program.getAccessControl(utils.pick(options, ['entity', 'bucket', 'default', 'file']), utils.makeHandler()); }) .command('delete ', 'Delete access controls from a bucket or file.', {}, function (options) { - program.deleteAccessControl(options, console.log); + program.deleteAccessControl(utils.pick(options, ['entity', 'bucket', 'default', 'file']), utils.makeHandler()); }) .example('node $0 add user-bob@domain.com OWNER -b mybucket', 'Add OWNER access controls for "user-bob@domain.com" to "mybucket".') .example('node $0 add viewers-2256 WRITER -b mybucket -d', 'Add default WRITER access controls to "mybucket" for "viewers-2256".') diff --git a/storage/buckets.js b/storage/buckets.js index d78a48c300..9d002d4346 100644 --- a/storage/buckets.js +++ b/storage/buckets.js @@ -91,6 +91,7 @@ function deleteBucket (name, callback) { // The command-line program var cli = require('yargs'); +var utils = require('../utils'); var program = module.exports = { createBucket: createBucket, @@ -105,13 +106,13 @@ var program = module.exports = { cli .demand(1) .command('create ', 'Create a new bucket with the given name.', {}, function (options) { - program.createBucket(options.bucket, console.log); + program.createBucket(options.bucket, utils.makeHandler(false)); }) .command('list', 'List all buckets in the authenticated project.', {}, function () { - program.listBuckets(console.log); + program.listBuckets(utils.makeHandler(true, 'name')); }) .command('delete ', 'Delete the specified bucket.', {}, function (options) { - program.deleteBucket(options.bucket, console.log); + program.deleteBucket(options.bucket, utils.makeHandler(false)); }) .example('node $0 create my-bucket', 'Create a new bucket named "my-bucket".') .example('node $0 list', 'List all buckets in the authenticated project.') diff --git a/storage/encryption.js b/storage/encryption.js index 7335981814..83fa5848d4 100644 --- a/storage/encryption.js +++ b/storage/encryption.js @@ -130,6 +130,7 @@ function rotateEncryptionKey (callback) { // The command-line program var cli = require('yargs'); +var utils = require('../utils'); var program = module.exports = { generateEncryptionKey: generateEncryptionKey, @@ -148,13 +149,13 @@ cli program.generateEncryptionKey(); }) .command('upload ', 'Upload an encrypted file to a bucket.', {}, function (options) { - program.uploadEncryptedFile(options, console.log); + program.uploadEncryptedFile(utils.pick(options, ['bucket', 'srcFile', 'destFile', 'key']), utils.makeHandler(false)); }) .command('download ', 'Download an encrypted file from a bucket.', {}, function (options) { - program.downloadEncryptedFile(options, console.log); + program.downloadEncryptedFile(utils.pick(options, ['bucket', 'srcFile', 'destFile', 'key']), utils.makeHandler(false)); }) .command('rotate ', 'Rotate encryption keys for a file.', {}, function () { - program.rotateEncryptionKey(console.log); + program.rotateEncryptionKey(utils.makeHandler()); }) .example('node $0 generate-encryption-key', 'Generate a sample encryption key.') .example('node $0 upload my-bucket resources/test.txt file_encrypted.txt QxhqaZEqBGVTW55HhQw9Q=', 'Upload "resources/test.txt" to "gs://my-bucket/file_encrypted.txt".') diff --git a/storage/files.js b/storage/files.js index b045666890..32425641b1 100644 --- a/storage/files.js +++ b/storage/files.js @@ -279,6 +279,7 @@ function copyFile (options, callback) { // The command-line program var cli = require('yargs'); +var utils = require('../utils'); var program = module.exports = { listFiles: listFiles, @@ -313,31 +314,31 @@ cli } }, function (options) { if (options.prefix) { - program.listFilesByPrefix(options, console.log); + program.listFilesByPrefix(utils.pick(options, ['bucket', 'prefix', 'delimiter']), utils.makeHandler(true, 'name')); } else { - program.listFiles(options.bucket, console.log); + program.listFiles(options.bucket, utils.makeHandler(true, 'name')); } }) .command('upload ', 'Upload a local file to a bucket.', {}, function (options) { - program.uploadFile(options, console.log); + program.uploadFile(utils.pick(options, ['bucket', 'srcFile']), utils.makeHandler(false)); }) .command('download ', 'Download a file from a bucket.', {}, function (options) { - program.downloadFile(options, console.log); + program.downloadFile(utils.pick(options, ['bucket', 'srcFile', 'destFile']), utils.makeHandler(false)); }) .command('delete ', 'Delete a file from a bucket.', {}, function (options) { - program.deleteFile(options, console.log); + program.deleteFile(utils.pick(options, ['bucket', 'file']), utils.makeHandler(false)); }) .command('getMetadata ', 'Get metadata for a file in a bucket.', {}, function (options) { - program.getMetadata(options, console.log); + program.getMetadata(utils.pick(options, ['bucket', 'file']), utils.makeHandler()); }) .command('makePublic ', 'Make a file public in a bucket.', {}, function (options) { - program.makePublic(options, console.log); + program.makePublic(utils.pick(options, ['bucket', 'file']), utils.makeHandler(false)); }) .command('move ', 'Move a file to a new location within the same bucket, i.e. rename the file.', {}, function (options) { - program.moveFile(options, console.log); + program.moveFile(utils.pick(options, ['bucket', 'srcFile', 'destFile']), utils.makeHandler(false)); }) .command('copy ', 'Copy a file in a bucket to another bucket.', {}, function (options) { - program.copyFile(options, console.log); + program.copyFile(utils.pick(options, ['srcBucket', 'srcFile', 'destBucket', 'destFile']), utils.makeHandler(false)); }) .example('node $0 list my-bucket', 'List files in "my-bucket".') .example('node $0 list my-bucket -p public/', 'List files in "my-bucket" filtered by prefix "public/".') diff --git a/storage/test/acl.test.js b/storage/test/acl.test.js index b4aad8b18c..5931c583a9 100644 --- a/storage/test/acl.test.js +++ b/storage/test/acl.test.js @@ -369,7 +369,14 @@ describe('storage:acl', function () { sinon.stub(program, 'addAccessControl'); program.main(['add', entity, role, '-b', bucketName]); - assert(program.addAccessControl.calledOnce); + assert.equal(program.addAccessControl.calledOnce, true); + assert.deepEqual(program.addAccessControl.firstCall.args.slice(0, -1), [{ + entity: entity, + role: role, + bucket: bucketName, + default: false, + file: undefined + }]); }); it('should call getAccessControl', function () { @@ -377,7 +384,13 @@ describe('storage:acl', function () { sinon.stub(program, 'getAccessControl'); program.main(['get', entity, '-b', bucketName]); - assert(program.getAccessControl.calledOnce); + assert.equal(program.getAccessControl.calledOnce, true); + assert.deepEqual(program.getAccessControl.firstCall.args.slice(0, -1), [{ + entity: entity, + bucket: bucketName, + default: false, + file: undefined + }]); }); it('should call deleteAccessControl', function () { @@ -385,7 +398,13 @@ describe('storage:acl', function () { sinon.stub(program, 'deleteAccessControl'); program.main(['delete', entity, '-b', bucketName]); - assert(program.deleteAccessControl.calledOnce); + assert.equal(program.deleteAccessControl.calledOnce, true); + assert.deepEqual(program.deleteAccessControl.firstCall.args.slice(0, -1), [{ + entity: entity, + bucket: bucketName, + default: false, + file: undefined + }]); }); }); }); diff --git a/storage/test/buckets.test.js b/storage/test/buckets.test.js index c3ee06839a..787f1eb9be 100644 --- a/storage/test/buckets.test.js +++ b/storage/test/buckets.test.js @@ -147,8 +147,9 @@ describe('storage:buckets', function () { var program = getSample().program; sinon.stub(program, 'createBucket'); - program.main(['create', 'my-bucket']); - assert(program.createBucket.calledOnce); + program.main(['create', bucketName]); + assert.equal(program.createBucket.calledOnce, true); + assert.deepEqual(program.createBucket.firstCall.args.slice(0, -1), [bucketName]); }); it('should call listBuckets', function () { @@ -156,15 +157,17 @@ describe('storage:buckets', function () { sinon.stub(program, 'listBuckets'); program.main(['list']); - assert(program.listBuckets.calledOnce); + assert.equal(program.listBuckets.calledOnce, true); + assert.deepEqual(program.listBuckets.firstCall.args.slice(0, -1), []); }); it('should call deleteBucket', function () { var program = getSample().program; sinon.stub(program, 'deleteBucket'); - program.main(['delete', 'my-bucket']); - assert(program.deleteBucket.calledOnce); + program.main(['delete', bucketName]); + assert.equal(program.deleteBucket.calledOnce, true); + assert.deepEqual(program.deleteBucket.firstCall.args.slice(0, -1), [bucketName]); }); }); }); diff --git a/storage/test/encryption.test.js b/storage/test/encryption.test.js index 59ca5c2d9b..5f0d88e8d7 100644 --- a/storage/test/encryption.test.js +++ b/storage/test/encryption.test.js @@ -177,7 +177,8 @@ describe('storage:encryption', function () { sinon.stub(program, 'generateEncryptionKey'); program.main(['generate-encryption-key']); - assert(program.generateEncryptionKey.calledOnce); + assert.equal(program.generateEncryptionKey.calledOnce, true); + assert.deepEqual(program.generateEncryptionKey.firstCall.args.slice(0, -1), []); }); it('should call uploadEncryptedFile', function () { @@ -185,7 +186,13 @@ describe('storage:encryption', function () { sinon.stub(program, 'uploadEncryptedFile'); program.main(['upload', bucketName, fileName, fileName, key]); - assert(program.uploadEncryptedFile.calledOnce); + assert.equal(program.uploadEncryptedFile.calledOnce, true); + assert.deepEqual(program.uploadEncryptedFile.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + srcFile: fileName, + destFile: fileName, + key: key + }]); }); it('should call downloadEncryptedFile', function () { @@ -193,7 +200,13 @@ describe('storage:encryption', function () { sinon.stub(program, 'downloadEncryptedFile'); program.main(['download', bucketName, fileName, fileName, key]); - assert(program.downloadEncryptedFile.calledOnce); + assert.equal(program.downloadEncryptedFile.calledOnce, true); + assert.deepEqual(program.downloadEncryptedFile.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + srcFile: fileName, + destFile: fileName, + key: key + }]); }); it('should call rotateEncryptionKey', function () { @@ -201,7 +214,8 @@ describe('storage:encryption', function () { sinon.stub(program, 'rotateEncryptionKey'); program.main(['rotate', bucketName, fileName, key, key]); - assert(program.rotateEncryptionKey.calledOnce); + assert.equal(program.rotateEncryptionKey.calledOnce, true); + assert.deepEqual(program.rotateEncryptionKey.firstCall.args.slice(0, -1), []); }); }); }); diff --git a/storage/test/files.test.js b/storage/test/files.test.js index b5495b55b5..4a22092148 100644 --- a/storage/test/files.test.js +++ b/storage/test/files.test.js @@ -15,7 +15,10 @@ var proxyquire = require('proxyquire').noCallThru(); var bucketName = 'foo'; -var fileName = 'test.txt'; +var srcFileName = 'test1.txt'; +var destFileName = 'test2.txt'; +var movedFileName = 'test3.txt'; +var copiedFileName = 'test4.txt'; function getSample () { var filesMock = [ @@ -166,14 +169,14 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - srcFile: fileName + srcFile: srcFileName }; sample.program.uploadFile(options, callback); assert(sample.mocks.bucket.upload.calledOnce, 'upload called once'); assert.equal(sample.mocks.bucket.upload.firstCall.args.length, 2, 'upload received 2 arguments'); - assert.deepEqual(sample.mocks.bucket.upload.firstCall.args[0], fileName, 'upload received file name'); + assert.deepEqual(sample.mocks.bucket.upload.firstCall.args[0], srcFileName, 'upload received file name'); assert(callback.calledOnce, 'callback called once'); assert.equal(callback.firstCall.args.length, 2, 'callback received 2 arguments'); assert.ifError(callback.firstCall.args[0], 'callback did not receive error'); @@ -187,7 +190,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - srcFile: fileName + srcFile: srcFileName }; sample.mocks.bucket.upload = sinon.stub().callsArgWith(1, error); @@ -206,8 +209,8 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - srcFile: fileName, - destFile: fileName + srcFile: srcFileName, + destFile: destFileName }; sample.program.downloadFile(options, callback); @@ -229,8 +232,8 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - srcFile: fileName, - destFile: fileName + srcFile: srcFileName, + destFile: destFileName }; sample.mocks.file.download = sinon.stub().callsArgWith(1, error); @@ -249,7 +252,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - file: fileName + file: srcFileName }; sample.program.deleteFile(options, callback); @@ -268,7 +271,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - file: fileName + file: srcFileName }; sample.mocks.file.delete = sinon.stub().callsArgWith(0, error); @@ -287,7 +290,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - file: fileName + file: srcFileName }; sample.program.getMetadata(options, callback); @@ -307,7 +310,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - file: fileName + file: srcFileName }; sample.mocks.file.getMetadata = sinon.stub().callsArgWith(0, error); @@ -326,7 +329,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - file: fileName + file: srcFileName }; sample.program.makePublic(options, callback); @@ -345,7 +348,7 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - file: fileName + file: srcFileName }; sample.mocks.file.makePublic = sinon.stub().callsArgWith(0, error); @@ -364,8 +367,8 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - srcFile: fileName, - destFile: fileName + srcFile: srcFileName, + destFile: movedFileName }; sample.program.moveFile(options, callback); @@ -386,8 +389,8 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { bucket: bucketName, - srcFile: fileName, - destFile: fileName + srcFile: srcFileName, + destFile: movedFileName }; sample.mocks.file.move = sinon.stub().callsArgWith(1, error); @@ -406,8 +409,8 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { srcBucket: bucketName, - srcFile: fileName, - destFile: fileName, + srcFile: srcFileName, + destFile: copiedFileName, destBucket: bucketName }; @@ -428,8 +431,8 @@ describe('storage:files', function () { var callback = sinon.stub(); var options = { srcBucket: bucketName, - srcFile: fileName, - destFile: fileName, + srcFile: srcFileName, + destFile: copiedFileName, destBucket: bucketName }; sample.mocks.file.copy = sinon.stub().callsArgWith(1, error); @@ -449,7 +452,8 @@ describe('storage:files', function () { sinon.stub(program, 'listFiles'); program.main(['list', bucketName]); - assert(program.listFiles.calledOnce); + assert.equal(program.listFiles.calledOnce, true); + assert.deepEqual(program.listFiles.firstCall.args.slice(0, -1), [bucketName]); }); it('should call listFilesByPrefix', function () { @@ -457,63 +461,100 @@ describe('storage:files', function () { sinon.stub(program, 'listFilesByPrefix'); program.main(['list', bucketName, '-p', 'public/']); - assert(program.listFilesByPrefix.calledOnce); + assert.equal(program.listFilesByPrefix.calledOnce, true); + assert.deepEqual(program.listFilesByPrefix.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + prefix: 'public/', + delimiter: undefined + }]); }); it('should call uploadFile', function () { var program = getSample().program; sinon.stub(program, 'uploadFile'); - program.main(['upload', bucketName, fileName]); - assert(program.uploadFile.calledOnce); + program.main(['upload', bucketName, srcFileName]); + assert.equal(program.uploadFile.calledOnce, true); + assert.deepEqual(program.uploadFile.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + srcFile: srcFileName + }]); }); it('should call downloadFile', function () { var program = getSample().program; sinon.stub(program, 'downloadFile'); - program.main(['download', bucketName, fileName, fileName]); - assert(program.downloadFile.calledOnce); + program.main(['download', bucketName, srcFileName, destFileName]); + assert.equal(program.downloadFile.calledOnce, true); + assert.deepEqual(program.downloadFile.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + srcFile: srcFileName, + destFile: destFileName + }]); }); it('should call deleteFile', function () { var program = getSample().program; sinon.stub(program, 'deleteFile'); - program.main(['delete', bucketName, fileName]); - assert(program.deleteFile.calledOnce); + program.main(['delete', bucketName, srcFileName]); + assert.equal(program.deleteFile.calledOnce, true); + assert.deepEqual(program.deleteFile.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + file: srcFileName + }]); }); it('should call getMetadata', function () { var program = getSample().program; sinon.stub(program, 'getMetadata'); - program.main(['getMetadata', bucketName, fileName]); - assert(program.getMetadata.calledOnce); + program.main(['getMetadata', bucketName, srcFileName]); + assert.equal(program.getMetadata.calledOnce, true); + assert.deepEqual(program.getMetadata.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + file: srcFileName + }]); }); it('should call makePublic', function () { var program = getSample().program; sinon.stub(program, 'makePublic'); - program.main(['makePublic', bucketName, fileName]); - assert(program.makePublic.calledOnce); + program.main(['makePublic', bucketName, srcFileName]); + assert.equal(program.makePublic.calledOnce, true); + assert.deepEqual(program.makePublic.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + file: srcFileName + }]); }); it('should call moveFile', function () { var program = getSample().program; sinon.stub(program, 'moveFile'); - program.main(['move', bucketName, fileName, fileName]); - assert(program.moveFile.calledOnce); + program.main(['move', bucketName, srcFileName, movedFileName]); + assert.equal(program.moveFile.calledOnce, true); + assert.deepEqual(program.moveFile.firstCall.args.slice(0, -1), [{ + bucket: bucketName, + srcFile: srcFileName, + destFile: movedFileName + }]); }); it('should call copyFile', function () { var program = getSample().program; sinon.stub(program, 'copyFile'); - program.main(['copy', bucketName, fileName, bucketName, fileName]); - assert(program.copyFile.calledOnce); + program.main(['copy', bucketName, srcFileName, bucketName, copiedFileName]); + assert.equal(program.copyFile.calledOnce, true); + assert.deepEqual(program.copyFile.firstCall.args.slice(0, -1), [{ + srcBucket: bucketName, + srcFile: srcFileName, + destBucket: bucketName, + destFile: copiedFileName + }]); }); }); }); diff --git a/storage/test/transfer.test.js b/storage/test/transfer.test.js index 63f61e00eb..e8a89e165e 100644 --- a/storage/test/transfer.test.js +++ b/storage/test/transfer.test.js @@ -14,7 +14,8 @@ 'use strict'; var proxyquire = require('proxyquire').noCallThru(); -var bucketName = 'foo'; +var srcBucketName = 'foo'; +var destBucketName = 'bar'; var jobName = 'transferJobs/123456789012345678'; var transferOperationName = 'transferOperations/123456789012345678'; @@ -68,8 +69,8 @@ describe('storage:transfer', function () { var date = '2016/08/11'; var time = '15:30'; var options = { - srcBucket: bucketName, - destBucket: bucketName, + srcBucket: srcBucketName, + destBucket: destBucketName, date: date, time: time }; @@ -484,8 +485,15 @@ describe('storage:transfer', function () { var program = getSample().program; sinon.stub(program, 'createTransferJob'); - program.main(['jobs', 'create', bucketName, bucketName, 'time', 'date']); - assert(program.createTransferJob.calledOnce); + program.main(['jobs', 'create', srcBucketName, destBucketName, 'time', 'date']); + assert.equal(program.createTransferJob.calledOnce, true); + assert.deepEqual(program.createTransferJob.firstCall.args.slice(0, -1), [{ + srcBucket: srcBucketName, + destBucket: destBucketName, + time: 'time', + date: 'date', + description: undefined + }]); }); it('should call getTransferJob', function () { @@ -493,7 +501,8 @@ describe('storage:transfer', function () { sinon.stub(program, 'getTransferJob'); program.main(['jobs', 'get', jobName]); - assert(program.getTransferJob.calledOnce); + assert.equal(program.getTransferJob.calledOnce, true); + assert.deepEqual(program.getTransferJob.firstCall.args.slice(0, -1), [jobName]); }); it('should call listTransferJobs', function () { @@ -501,7 +510,8 @@ describe('storage:transfer', function () { sinon.stub(program, 'listTransferJobs'); program.main(['jobs', 'list']); - assert(program.listTransferJobs.calledOnce); + assert.equal(program.listTransferJobs.calledOnce, true); + assert.deepEqual(program.listTransferJobs.firstCall.args.slice(0, -1), []); }); it('should call updateTransferJob', function () { @@ -509,7 +519,12 @@ describe('storage:transfer', function () { sinon.stub(program, 'updateTransferJob'); program.main(['jobs', 'set', jobName, 'status', 'DISABLED']); - assert(program.updateTransferJob.calledOnce); + assert.equal(program.updateTransferJob.calledOnce, true); + assert.deepEqual(program.updateTransferJob.firstCall.args.slice(0, -1), [{ + job: jobName, + field: 'status', + value: 'DISABLED' + }]); }); it('should call listTransferOperations', function () { @@ -517,7 +532,17 @@ describe('storage:transfer', function () { sinon.stub(program, 'listTransferOperations'); program.main(['operations', 'list']); - assert(program.listTransferOperations.calledOnce); + assert.equal(program.listTransferOperations.calledOnce, true); + assert.deepEqual(program.listTransferOperations.firstCall.args.slice(0, -1), [undefined]); + }); + + it('should call listTransferOperations and filter', function () { + var program = getSample().program; + + sinon.stub(program, 'listTransferOperations'); + program.main(['operations', 'list', jobName]); + assert.equal(program.listTransferOperations.calledOnce, true); + assert.deepEqual(program.listTransferOperations.firstCall.args.slice(0, -1), [jobName]); }); it('should call getTransferOperation', function () { @@ -525,7 +550,8 @@ describe('storage:transfer', function () { sinon.stub(program, 'getTransferOperation'); program.main(['operations', 'get', transferOperationName]); - assert(program.getTransferOperation.calledOnce); + assert.equal(program.getTransferOperation.calledOnce, true); + assert.deepEqual(program.getTransferOperation.firstCall.args.slice(0, -1), [transferOperationName]); }); it('should call pauseTransferOperation', function () { @@ -533,7 +559,8 @@ describe('storage:transfer', function () { sinon.stub(program, 'pauseTransferOperation'); program.main(['operations', 'pause', transferOperationName]); - assert(program.pauseTransferOperation.calledOnce); + assert.equal(program.pauseTransferOperation.calledOnce, true); + assert.deepEqual(program.pauseTransferOperation.firstCall.args.slice(0, -1), [transferOperationName]); }); it('should call resumeTransferOperation', function () { @@ -541,7 +568,8 @@ describe('storage:transfer', function () { sinon.stub(program, 'resumeTransferOperation'); program.main(['operations', 'resume', transferOperationName]); - assert(program.resumeTransferOperation.calledOnce); + assert.equal(program.resumeTransferOperation.calledOnce, true); + assert.deepEqual(program.resumeTransferOperation.firstCall.args.slice(0, -1), [transferOperationName]); }); }); }); diff --git a/storage/transfer.js b/storage/transfer.js index 1958eff15b..dbce782e35 100644 --- a/storage/transfer.js +++ b/storage/transfer.js @@ -346,6 +346,7 @@ function resumeTransferOperation (transferOperationName, callback) { // The command-line program var cli = require('yargs'); +var utils = require('../utils'); var program = module.exports = { createTransferJob: createTransferJob, @@ -368,16 +369,16 @@ cli yargs .demand(2) .command('create