Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add requester pays samples #453

Merged
merged 7 commits into from
Aug 15, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this string use single-quotes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, the other strings should use backticks. Will fix.

} 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`, `Disables requester-pays requests on a bucket named "my-bucket".`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last nit, disable should accept a bucket id similar to enable.

.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/[email protected].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/[email protected].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 @@ [email protected]:
text-encoding "0.6.4"
type-detect "^4.0.0"

[email protected]:
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