Skip to content

Commit

Permalink
Add requester pays samples (#453)
Browse files Browse the repository at this point in the history
* Add requester pays samples

* Fix comment

* Update dependency to fix test

* Add README

* Fix typo

* Switch to backticks

* Whoops, fix nit
  • Loading branch information
Ace Nassri authored Aug 15, 2017
1 parent ab961b5 commit ffcba44
Show file tree
Hide file tree
Showing 5 changed files with 340 additions and 5 deletions.
34 changes: 34 additions & 0 deletions storage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* [Encryption](#encryption)
* [Files](#files)
* [Storage Transfer API](#storage-transfer-api)
* [Requester Pays samples](#requester-pays-samples)
* [Running the tests](#running-the-tests)

## Setup
Expand Down Expand Up @@ -199,6 +200,39 @@ For more information, see https://cloud.google.com/storage/transfer
[transfer_4_docs]: https://cloud.google.com/storage/transfer
[transfer_4_code]: transfer.js

### Requester Pays samples

View the [documentation][requesterPays_5_docs] or the [source code][requesterPays_5_code].

__Usage:__ `node requesterPays.js --help`

```
Commands:
enable <bucket> Enables requester-pays requests on a bucket.
disable <bucket> Disables requester-pays requests on a bucket.
get-status <bucket> Determines whether requester-pays requests are enabled on a
bucket.
download <bucketName> <srcFileName> <destFileName> Downloads a file from a bucket using requester-pays requests.
Options:
--help Show help [boolean]
Examples:
node requesterPays.js enable my-bucket Enables requester-pays requests on a bucket named
"my-bucket".
node requesterPays.js disable my-bucket Disables requester-pays requests on a bucket named
"my-bucket".
node requesterPays.js get-status my-bucket Determines whether requester-pays requests are enabled
for a bucket named "my-bucket".
node requesterPays.js download my-bucket file.txt ./file.txt Downloads "gs://my-bucket/file.txt" to "./file.txt"
using requester-pays requests.
For more information, see https://cloud.google.com/storage/docs
```

[requesterPays_5_docs]: https://cloud.google.com/storage/docs
[requesterPays_5_code]: requesterPays.js

## Running the tests

1. Set the **GCLOUD_PROJECT** and **GOOGLE_APPLICATION_CREDENTIALS** environment variables.
Expand Down
9 changes: 8 additions & 1 deletion storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"yargs": "8.0.2"
},
"devDependencies": {
"@google-cloud/nodejs-repo-tools": "1.4.16",
"@google-cloud/nodejs-repo-tools": "1.4.17",
"ava": "0.21.0",
"proxyquire": "1.8.0",
"sinon": "3.0.0",
Expand Down Expand Up @@ -71,6 +71,13 @@
"file": "transfer.js",
"docs_link": "https://cloud.google.com/storage/transfer",
"usage": "node transfer.js --help"
},
{
"id": "requesterPays",
"name": "Requester Pays samples",
"file": "requesterPays.js",
"docs_link": "https://cloud.google.com/storage/docs",
"usage": "node requesterPays.js --help"
}
]
}
Expand Down
191 changes: 191 additions & 0 deletions storage/requesterPays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/**
* Copyright 2017, Google, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* This application demonstrates how to perform basic operations on buckets with
* the Google Cloud Storage API.
*
* For more information, see the README.md under /storage and the documentation
* at https://cloud.google.com/storage/docs.
*/

'use strict';

function enableRequesterPays (bucketName) {
// [START enable_requester_pays]
// Imports the Google Cloud client library
const Storage = require(`@google-cloud/storage`);

// The name of the bucket to enable requester-paying for, e.g. "my-bucket"
// const bucketName = "my-bucket";

// Instantiates a client
const storage = Storage();

// Enables requester-pays requests
storage
.bucket(bucketName)
.enableRequesterPays()
.then(() => {
console.log(`Requester-pays requests have been enabled for bucket ${bucketName}.`);
})
.catch((err) => {
console.error(`ERROR:`, err);
});
// [END enable_requester_pays]
}

function disableRequesterPays (bucketName) {
// [START disable_requester_pays]
// Imports the Google Cloud client library
const Storage = require(`@google-cloud/storage`);

// The name of the bucket to disable requester-paying for, e.g. "my-bucket"
// const bucketName = "my-bucket";

// Instantiates a client
const storage = Storage();

// Disables requester-pays requests
storage
.bucket(bucketName)
.disableRequesterPays()
.then(() => {
console.log(`Requester-pays requests have been disabled for bucket ${bucketName}.`);
})
.catch((err) => {
console.error(`ERROR:`, err);
});
// [END disable_requester_pays]
}

function getRequesterPaysStatus (bucketName) {
// [START get_requester_pays_status]
// Imports the Google Cloud client library
const Storage = require(`@google-cloud/storage`);

// The name of the bucket to get the requester-payable status for, e.g. "my-bucket"
// const bucketName = "my-bucket";

// Instantiates a client
const storage = Storage();

// Gets the requester-pays status of a bucket
storage
.bucket(bucketName)
.getMetadata()
.then((data) => {
let status;
const metadata = data[0];
if (metadata && metadata.billing && metadata.billing.requesterPays) {
status = `enabled`;
} else {
status = `disabled`;
}
console.log(`Requester-pays requests are ${status} for bucket ${bucketName}.`);
})
.catch((err) => {
console.error(`ERROR:`, err);
});
// [END get_requester_pays_status]
}

function downloadFileUsingRequesterPays (projectId, bucketName, srcFilename, destFilename) {
// [START storage_download_file_requester_pays]
// Imports the Google Cloud client library
const Storage = require(`@google-cloud/storage`);

// The project ID to bill from
// const projectId = process.env.GCLOUD_PROJECT;

// The name of the bucket to access, e.g. "my-bucket"
// const bucketName = "my-bucket";

// The name of the remote file to download, e.g. "file.txt"
// const srcFilename = "file.txt";

// The path to which the file should be downloaded, e.g. "./local/path/to/file.txt"
// const destFilename = "./local/path/to/file.txt";

// Instantiates a client
const storage = Storage();

const options = {
// The path to which the file should be downloaded, e.g. "./file.txt"
destination: destFilename,

// The project to bill from, if requester-pays requests are enabled
userProject: projectId
};

// Downloads the file
storage
.bucket(bucketName)
.file(srcFilename)
.download(options)
.then(() => {
console.log(`gs://${bucketName}/${srcFilename} downloaded to ${destFilename} using requester-pays requests.`);
})
.catch((err) => {
console.error(`ERROR:`, err);
});
// [END storage_download_file_requester_pays]
}

const cli = require(`yargs`)
.demand(1)
.command(
`enable <bucket>`,
`Enables requester-pays requests on a bucket.`,
{},
(opts) => enableRequesterPays(opts.bucket)
)
.command(
`disable <bucket>`,
`Disables requester-pays requests on a bucket.`,
{},
(opts) => disableRequesterPays(opts.bucket)
)
.command(
`get-status <bucket>`,
`Determines whether requester-pays requests are enabled on a bucket.`,
{},
(opts) => getRequesterPaysStatus(opts.bucket)
)
.command(
`download <bucketName> <srcFileName> <destFileName>`,
`Downloads a file from a bucket using requester-pays requests.`,
{
projectId: {
type: `string`,
alias: `p`,
default: process.env.GCLOUD_PROJECT
}
},
(opts) => downloadFileUsingRequesterPays(opts.projectId, opts.bucketName, opts.srcFileName, opts.destFileName)
)
.example(`node $0 enable my-bucket`, `Enables requester-pays requests on a bucket named "my-bucket".`)
.example(`node $0 disable my-bucket`, `Disables requester-pays requests on a bucket named "my-bucket".`)
.example(`node $0 get-status my-bucket`, `Determines whether requester-pays requests are enabled for a bucket named "my-bucket".`)
.example(`node $0 download my-bucket file.txt ./file.txt`, `Downloads "gs://my-bucket/file.txt" to "./file.txt" using requester-pays requests.`)
.wrap(120)
.recommendCommands()
.epilogue(`For more information, see https://cloud.google.com/storage/docs`)
.help()
.strict();

if (module === require.main) {
cli.parse(process.argv.slice(2));
}
89 changes: 89 additions & 0 deletions storage/system-test/requesterPays.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Copyright 2017, Google, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const fs = require(`fs`);
const path = require(`path`);
const storage = require(`@google-cloud/storage`)();
const test = require(`ava`);
const tools = require(`@google-cloud/nodejs-repo-tools`);
const uuid = require(`uuid`);

const cwd = path.join(__dirname, `..`);
const cmd = `node requesterPays.js`;
const bucketName = `nodejs-docs-samples-test-${uuid.v4()}`;
const fileName = `test.txt`;
const bucket = storage.bucket(bucketName);

const uploadFilePath = path.join(cwd, `resources`, fileName);
const downloadFilePath = path.join(__dirname, `test_${uuid.v4()}.txt`);

test.before(async () => {
tools.checkCredentials();
await bucket.create();

// Upload a test file (to download later)
await bucket.upload(uploadFilePath);
});
test.after.always(async () => {
try {
fs.unlinkSync(downloadFilePath);
} catch (err) {
console.log(err);
}
// Try deleting all files twice, just to make sure
try {
await bucket.deleteFiles({ force: true });
} catch (err) {} // ignore error
try {
await bucket.deleteFiles({ force: true });
} catch (err) {} // ignore error
try {
await bucket.delete();
} catch (err) {} // ignore error
});

test.serial(`should fetch requester-pays status on a default bucket`, async (t) => {
const output = await tools.runAsync(`${cmd} get-status ${bucketName}`, cwd);
t.is(output, `Requester-pays requests are disabled for bucket ${bucketName}.`);
});

test.serial(`should enable requester-pays requests`, async (t) => {
const output = await tools.runAsync(`${cmd} enable ${bucketName}`, cwd);
t.is(output, `Requester-pays requests have been enabled for bucket ${bucketName}.`);
});

test.serial(`should fetch requester-pays status on a modified bucket`, async (t) => {
const output = await tools.runAsync(`${cmd} get-status ${bucketName}`, cwd);
t.is(output, `Requester-pays requests are enabled for bucket ${bucketName}.`);
});

test.serial(`should download a file using requester-pays requests`, async (t) => {
const output = await tools.runAsync(`${cmd} download ${bucketName} ${fileName} ${downloadFilePath}`, cwd);
t.is(output, `gs://${bucketName}/${fileName} downloaded to ${downloadFilePath} using requester-pays requests.`);
await t.notThrows(() => fs.statSync(downloadFilePath));
});

test.serial(`should disable requester-pays requests`, async (t) => {
const output = await tools.runAsync(`${cmd} disable ${bucketName}`, cwd);
t.is(output, `Requester-pays requests have been disabled for bucket ${bucketName}.`);
});

test.serial(`should error on requester-pays requests if they are disabled`, async (t) => {
const result = await tools.runAsyncWithIO(`${cmd} download ${bucketName} ${fileName} ${downloadFilePath}`, cwd);
t.truthy(result.stderr);
t.regex(result.stderr, /User project prohibited for non requester pays bucket/);
});
22 changes: 18 additions & 4 deletions storage/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@
string-format-obj "^1.1.0"
through2 "^2.0.3"

"@google-cloud/nodejs-repo-tools@1.4.16":
version "1.4.16"
resolved "https://registry.yarnpkg.com/@google-cloud/nodejs-repo-tools/-/nodejs-repo-tools-1.4.16.tgz#a87b1f9db8426494ee7ea21a3a0cf172c66fe350"
"@google-cloud/nodejs-repo-tools@1.4.17":
version "1.4.17"
resolved "https://registry.yarnpkg.com/@google-cloud/nodejs-repo-tools/-/nodejs-repo-tools-1.4.17.tgz#6458d12467cf93dc931d64640afabca1dfc19af2"
dependencies:
ava "0.21.0"
colors "1.1.2"
Expand All @@ -78,7 +78,7 @@
handlebars "4.0.10"
lodash "4.17.4"
proxyquire "1.8.0"
sinon "3.0.0"
sinon "3.2.0"
string "3.3.3"
supertest "3.0.0"
yargs "8.0.2"
Expand Down Expand Up @@ -2910,6 +2910,20 @@ sinon@3.0.0:
text-encoding "0.6.4"
type-detect "^4.0.0"

sinon@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/sinon/-/sinon-3.2.0.tgz#8848a66ab6e8b80b5532e3824f59f83ea2628c77"
dependencies:
diff "^3.1.0"
formatio "1.2.0"
lolex "^2.1.2"
native-promise-only "^0.8.1"
nise "^1.0.1"
path-to-regexp "^1.7.0"
samsam "^1.1.3"
text-encoding "0.6.4"
type-detect "^4.0.0"

slash@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
Expand Down

0 comments on commit ffcba44

Please sign in to comment.