diff --git a/samples/changeFileCSEKToCMEK.js b/samples/changeFileCSEKToCMEK.js index 6e126a275..eb6745abd 100644 --- a/samples/changeFileCSEKToCMEK.js +++ b/samples/changeFileCSEKToCMEK.js @@ -23,7 +23,8 @@ function main( bucketName = 'my-bucket', fileName = 'test.txt', encryptionKey = 'my-encription-key', - kmsKeyName = 'my-kms-key' + kmsKeyName = 'my-kms-key', + generationMatchPrecondition = 0 ) { // [START storage_object_csek_to_cmek] /** @@ -49,13 +50,25 @@ function main( const storage = new Storage(); async function changeFileCSEKToCMEK() { + const rotateEncryptionKeyOptions = { + kmsKeyName, + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + preconditionOpts: { + ifGenerationMatch: generationMatchPrecondition, + }, + }; + + console.log(rotateEncryptionKeyOptions); + await storage .bucket(bucketName) .file(fileName, { encryptionKey: Buffer.from(encryptionKey, 'base64'), }) .rotateEncryptionKey({ - kmsKeyName, + rotateEncryptionKeyOptions, }); console.log( diff --git a/samples/composeFile.js b/samples/composeFile.js index e5ecdd572..332c3da9c 100644 --- a/samples/composeFile.js +++ b/samples/composeFile.js @@ -23,7 +23,8 @@ function main( bucketName = 'my-bucket', firstFileName = 'file-one.txt', secondFileName = 'file-two.txt', - destinationFileName = 'file-one-two.txt' + destinationFileName = 'file-one-two.txt', + destinationGenerationMatchPrecondition = 0 ) { // [START storage_compose_file] /** @@ -51,7 +52,17 @@ function main( const bucket = storage.bucket(bucketName); const sources = [firstFileName, secondFileName]; - await bucket.combine(sources, destinationFileName); + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + const combineOptions = { + ifGenerationMatch: destinationGenerationMatchPrecondition, + }; + await bucket.combine(sources, destinationFileName, combineOptions); console.log( `New composite file ${destinationFileName} was created by combining ${firstFileName} and ${secondFileName}` diff --git a/samples/copyFile.js b/samples/copyFile.js index d0118ee2d..10f1eb4a6 100644 --- a/samples/copyFile.js +++ b/samples/copyFile.js @@ -24,7 +24,8 @@ function main( srcBucketName = 'my-bucket', srcFilename = 'test2.txt', destBucketName = 'my-bucket', - destFileName = 'test3.txt' + destFileName = 'test3.txt', + destinationGenerationMatchPrecondition = 0 ) { // [START storage_copy_file] /** @@ -49,11 +50,26 @@ function main( const storage = new Storage(); async function copyFile() { + const copyDestination = storage.bucket(destBucketName).file(destFileName); + + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + const copyOptions = { + preconditionOpts: { + ifGenerationMatch: destinationGenerationMatchPrecondition, + }, + }; + // Copies the file to the other bucket await storage .bucket(srcBucketName) .file(srcFilename) - .copy(storage.bucket(destBucketName).file(destFileName)); + .copy(copyDestination, copyOptions); console.log( `gs://${srcBucketName}/${srcFilename} copied to gs://${destBucketName}/${destFileName}` diff --git a/samples/copyOldVersionOfFile.js b/samples/copyOldVersionOfFile.js index d60dcb430..11c8973b4 100644 --- a/samples/copyOldVersionOfFile.js +++ b/samples/copyOldVersionOfFile.js @@ -24,7 +24,8 @@ function main( srcFilename = 'test2.txt', destBucketName = 'my-bucket', destFileName = 'test3.txt', - generation = 1 + generation = 1, + destinationGenerationMatchPrecondition = 0 ) { // [START storage_copy_file_archived_generation] /** @@ -53,12 +54,26 @@ function main( async function copyOldVersionOfFile() { // Copies the file to the other bucket + + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + const copyOptions = { + preconditionOpts: { + ifGenerationMatch: destinationGenerationMatchPrecondition, + }, + }; + await storage .bucket(srcBucketName) .file(srcFilename, { generation, }) - .copy(storage.bucket(destBucketName).file(destFileName)); + .copy(storage.bucket(destBucketName).file(destFileName), copyOptions); console.log( `Generation ${generation} of file ${srcFilename} in bucket ${srcBucketName} was copied to ${destFileName} in bucket ${destBucketName}` diff --git a/samples/deleteFile.js b/samples/deleteFile.js index f5ec0c526..37391dabf 100644 --- a/samples/deleteFile.js +++ b/samples/deleteFile.js @@ -20,7 +20,11 @@ * at https://cloud.google.com/storage/docs. */ -function main(bucketName = 'my-bucket', fileName = 'test.txt') { +function main( + bucketName = 'my-bucket', + fileName = 'test.txt', + generationMatchPrecondition = 0 +) { // [START storage_delete_file] /** * TODO(developer): Uncomment the following lines before running the sample. @@ -37,8 +41,18 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') { // Creates a client const storage = new Storage(); + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + const deleteOptions = { + ifGenerationMatch: generationMatchPrecondition, + }; async function deleteFile() { - await storage.bucket(bucketName).file(fileName).delete(); + await storage.bucket(bucketName).file(fileName).delete(deleteOptions); console.log(`gs://${bucketName}/${fileName} deleted`); } diff --git a/samples/fileChangeStorageClass.js b/samples/fileChangeStorageClass.js index 3fe8c3dd2..c44a3d184 100644 --- a/samples/fileChangeStorageClass.js +++ b/samples/fileChangeStorageClass.js @@ -22,7 +22,8 @@ function main( bucketName = 'my-bucket', fileName = 'file.txt', - storageClass = 'standard' + storageClass = 'standard', + generationMatchPrecondition = 0 ) { // [START storage_change_file_storage_class] // Imports the Google Cloud client library @@ -46,10 +47,21 @@ function main( // const storageClass = 'coldline'; async function fileChangeStorageClass() { + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + const setStorageClassOptions = { + ifGenerationMatch: generationMatchPrecondition, + }; + await storage .bucket(bucketName) .file(fileName) - .setStorageClass(storageClass); + .setStorageClass(storageClass, setStorageClassOptions); console.log(`${fileName} has been set to ${storageClass}`); } diff --git a/samples/fileSetMetadata.js b/samples/fileSetMetadata.js index 1fd178532..15a3fdb3c 100644 --- a/samples/fileSetMetadata.js +++ b/samples/fileSetMetadata.js @@ -19,7 +19,11 @@ // description: Set file metadata. // usage: node fileSetMetadata.js -function main(bucketName = 'my-bucket', fileName = 'file.txt') { +function main( + bucketName = 'my-bucket', + fileName = 'file.txt', + generationMatchPrecondition = 0 +) { // [START storage_set_metadata] // Imports the Google Cloud client library const {Storage} = require('@google-cloud/storage'); @@ -37,23 +41,34 @@ function main(bucketName = 'my-bucket', fileName = 'file.txt') { // const fileName = 'your-file-name'; async function setFileMetadata() { + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + const options = { + ifGenerationMatch: generationMatchPrecondition, + }; + // Set file metadata. const [metadata] = await storage .bucket(bucketName) .file(fileName) - .setMetadata({ - // Predefined metadata for server e.g. 'cacheControl', 'contentDisposition', - // 'contentEncoding', 'contentLanguage', 'contentType' - contentDisposition: 'attachment; filename*=utf-8\'\'"anotherImage.jpg"', - contentType: 'image/jpeg', + .setMetadata( + { + // Predefined metadata for server e.g. 'cacheControl', 'contentDisposition', + // 'contentEncoding', 'contentLanguage', 'contentType' + contentDisposition: + 'attachment; filename*=utf-8\'\'"anotherImage.jpg"', + contentType: 'image/jpeg', - // A note or actionable items for user e.g. uniqueId, object description, - // or other useful information. - metadata: { - description: 'file description...', - modified: '1900-01-01', + // A note or actionable items for user e.g. uniqueId, object description, + // or other useful information. + metadata: { + description: 'file description...', + modified: '1900-01-01', + }, }, - }); + options + ); console.log( 'Updated metadata for object', diff --git a/samples/moveFile.js b/samples/moveFile.js index 723cc043a..ce700648e 100644 --- a/samples/moveFile.js +++ b/samples/moveFile.js @@ -23,7 +23,8 @@ function main( bucketName = 'my-bucket', srcFileName = 'test.txt', - destFileName = 'test2.txt' + destFileName = 'test2.txt', + destinationGenerationMatchPrecondition = 0 ) { // [START storage_move_file] /** @@ -45,8 +46,24 @@ function main( const storage = new Storage(); async function moveFile() { + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + const moveOptions = { + preconditionOpts: { + ifGenerationMatch: destinationGenerationMatchPrecondition, + }, + }; + // Moves the file within the bucket - await storage.bucket(bucketName).file(srcFileName).move(destFileName); + await storage + .bucket(bucketName) + .file(srcFileName) + .move(destFileName, moveOptions); console.log( `gs://${bucketName}/${srcFileName} moved to gs://${bucketName}/${destFileName}` diff --git a/samples/releaseEventBasedHold.js b/samples/releaseEventBasedHold.js index e73dce03f..1360b8f84 100644 --- a/samples/releaseEventBasedHold.js +++ b/samples/releaseEventBasedHold.js @@ -20,7 +20,11 @@ * at https://cloud.google.com/storage/docs/bucket-lock */ -function main(bucketName = 'my-bucket', fileName = 'test.txt') { +function main( + bucketName = 'my-bucket', + fileName = 'test.txt', + generationMatchPrecondition = 0 +) { // [START storage_release_event_based_hold] /** * TODO(developer): Uncomment the following lines before running the sample. @@ -38,9 +42,19 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') { const storage = new Storage(); async function releaseEventBasedHold() { - await storage.bucket(bucketName).file(fileName).setMetadata({ - eventBasedHold: false, - }); + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + const options = { + ifGenerationMatch: generationMatchPrecondition, + }; + + await storage.bucket(bucketName).file(fileName).setMetadata( + { + eventBasedHold: false, + }, + options + ); console.log(`Event-based hold was released for ${fileName}.`); } diff --git a/samples/releaseTemporaryHold.js b/samples/releaseTemporaryHold.js index 970236a3f..ae9d013b9 100644 --- a/samples/releaseTemporaryHold.js +++ b/samples/releaseTemporaryHold.js @@ -20,7 +20,11 @@ * at https://cloud.google.com/storage/docs/bucket-lock */ -function main(bucketName = 'my-bucket', fileName = 'test.txt') { +function main( + bucketName = 'my-bucket', + fileName = 'test.txt', + generationMatchPrecondition = 0 +) { // [START storage_release_temporary_hold] /** * TODO(developer): Uncomment the following lines before running the sample. @@ -38,9 +42,19 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') { const storage = new Storage(); async function releaseTemporaryHold() { - await storage.bucket(bucketName).file(fileName).setMetadata({ - temporaryHold: false, - }); + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + const options = { + ifGenerationMatch: generationMatchPrecondition, + }; + + await storage.bucket(bucketName).file(fileName).setMetadata( + { + temporaryHold: false, + }, + options + ); console.log(`Temporary hold was released for ${fileName}.`); } diff --git a/samples/rotateEncryptionKey.js b/samples/rotateEncryptionKey.js index 1b81f4709..3f0f174da 100644 --- a/samples/rotateEncryptionKey.js +++ b/samples/rotateEncryptionKey.js @@ -24,7 +24,8 @@ function main( bucketName = 'my-bucket', fileName = 'test.txt', oldKey = process.env.GOOGLE_CLOUD_KMS_KEY_US, - newKey = process.env.GOOGLE_CLOUD_KMS_KEY_ASIA + newKey = process.env.GOOGLE_CLOUD_KMS_KEY_ASIA, + generationMatchPrecondition = 0 ) { // [START storage_rotate_encryption_key] /** @@ -53,13 +54,23 @@ function main( const storage = new Storage(); async function rotateEncryptionKey() { + const rotateEncryptionKeyOptions = { + encryptionKey: Buffer.from(newKey, 'base64'), + + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + preconditionOpts: { + ifGenerationMatch: generationMatchPrecondition, + }, + }; await storage .bucket(bucketName) .file(fileName, { encryptionKey: Buffer.from(oldKey, 'base64'), }) .rotateEncryptionKey({ - encryptionKey: Buffer.from(newKey, 'base64'), + rotateEncryptionKeyOptions, }); console.log('Encryption key rotated successfully'); diff --git a/samples/setEventBasedHold.js b/samples/setEventBasedHold.js index 06a09070b..0a8b46c54 100644 --- a/samples/setEventBasedHold.js +++ b/samples/setEventBasedHold.js @@ -20,7 +20,11 @@ * at https://cloud.google.com/storage/docs/bucket-lock */ -function main(bucketName = 'my-bucket', fileName = 'test.txt') { +function main( + bucketName = 'my-bucket', + fileName = 'test.txt', + generationMatchPrecondition = 0 +) { // [START storage_set_event_based_hold] /** * TODO(developer): Uncomment the following lines before running the sample. @@ -38,10 +42,20 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') { const storage = new Storage(); async function setEventBasedHold() { + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + const options = { + ifGenerationMatch: generationMatchPrecondition, + }; + // Set event-based hold - await storage.bucket(bucketName).file(fileName).setMetadata({ - eventBasedHold: true, - }); + await storage.bucket(bucketName).file(fileName).setMetadata( + { + eventBasedHold: true, + }, + options + ); console.log(`Event-based hold was set for ${fileName}.`); } diff --git a/samples/setTemporaryHold.js b/samples/setTemporaryHold.js index d83ac10d3..23a8ae016 100644 --- a/samples/setTemporaryHold.js +++ b/samples/setTemporaryHold.js @@ -20,7 +20,11 @@ * at https://cloud.google.com/storage/docs/bucket-lock */ -function main(bucketName = 'my-bucket', fileName = 'test.txt') { +function main( + bucketName = 'my-bucket', + fileName = 'test.txt', + generationMatchPrecondition = 0 +) { // [START storage_set_temporary_hold] /** * TODO(developer): Uncomment the following lines before running the sample. @@ -38,9 +42,19 @@ function main(bucketName = 'my-bucket', fileName = 'test.txt') { const storage = new Storage(); async function setTemporaryHold() { - await storage.bucket(bucketName).file(fileName).setMetadata({ - temporaryHold: true, - }); + // Optional: set a generation-match precondition to avoid potential race + // conditions and data corruptions. The request to upload is aborted if the + // object's generation number does not match your precondition. + const options = { + ifGenerationMatch: generationMatchPrecondition, + }; + + await storage.bucket(bucketName).file(fileName).setMetadata( + { + temporaryHold: true, + }, + options + ); console.log(`Temporary hold was set for ${fileName}.`); } diff --git a/samples/system-test/bucketLock.test.js b/samples/system-test/bucketLock.test.js index 2ea645471..105240d6f 100644 --- a/samples/system-test/bucketLock.test.js +++ b/samples/system-test/bucketLock.test.js @@ -88,16 +88,18 @@ it('should disable default event-based hold on a bucket', () => { ); }); -it('should set an event-based hold on a file', () => { +it('should set an event-based hold on a file', async () => { + const [metadata] = await bucket.file(fileName).getMetadata(); const output = execSync( - `node setEventBasedHold.js ${bucketName} ${fileName}` + `node setEventBasedHold.js ${bucketName} ${fileName} ${metadata.generation}` ); assert.match(output, new RegExp(`Event-based hold was set for ${fileName}`)); }); -it('should release an event-based hold on a file', () => { +it('should release an event-based hold on a file', async () => { + const [metadata] = await bucket.file(fileName).getMetadata(); const output = execSync( - `node releaseEventBasedHold.js ${bucketName} ${fileName}` + `node releaseEventBasedHold.js ${bucketName} ${fileName} ${metadata.generation}` ); assert.match( output, @@ -113,14 +115,18 @@ it('should remove a retention policy on a bucket', () => { ); }); -it('should set an temporary hold on a file', () => { - const output = execSync(`node setTemporaryHold.js ${bucketName} ${fileName}`); +it('should set an temporary hold on a file', async () => { + const [metadata] = await bucket.file(fileName).getMetadata(); + const output = execSync( + `node setTemporaryHold.js ${bucketName} ${fileName} ${metadata.generation}` + ); assert.match(output, new RegExp(`Temporary hold was set for ${fileName}.`)); }); -it('should release an temporary hold on a file', () => { +it('should release an temporary hold on a file', async () => { + const [metadata] = await bucket.file(fileName).getMetadata(); const output = execSync( - `node releaseTemporaryHold.js ${bucketName} ${fileName}` + `node releaseTemporaryHold.js ${bucketName} ${fileName} ${metadata.generation}` ); assert.match( output, diff --git a/samples/system-test/encryption.test.js b/samples/system-test/encryption.test.js index 4a2f3a319..e970df61e 100644 --- a/samples/system-test/encryption.test.js +++ b/samples/system-test/encryption.test.js @@ -34,6 +34,7 @@ const kmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_US; const fileName = 'test.txt'; const filePath = path.join(__dirname, '../resources', fileName); const downloadFilePath = path.join(__dirname, '../resources/downloaded.txt'); +const doesNotExistPrecondition = 0; const key = crypto.randomBytes(32).toString('base64'); @@ -56,7 +57,7 @@ it('should generate a key', () => { it('should upload a file', async () => { const output = execSync( - `node uploadEncryptedFile.js ${bucketName} ${filePath} ${fileName} ${key}` + `node uploadEncryptedFile.js ${bucketName} ${filePath} ${fileName} ${key} ${doesNotExistPrecondition}` ); assert.match( output, @@ -77,10 +78,14 @@ it('should download a file', () => { fs.statSync(downloadFilePath); }); -it('should rotate keys', () => { +it('should rotate keys', async () => { const newKey = crypto.randomBytes(32).toString('base64'); + const [metadata] = await storage + .bucket(bucketName) + .file(fileName) + .getMetadata(); const output = execSync( - `node rotateEncryptionKey.js ${bucketName} ${fileName} ${key} ${newKey}` + `node rotateEncryptionKey.js ${bucketName} ${fileName} ${key} ${newKey} ${metadata.generation}` ); assert.include(output, 'Encryption key rotated successfully'); }); @@ -90,9 +95,13 @@ it('should convert CSEK to KMS key', async () => { const file = bucket.file(encryptedFileName, { encryptionKey: Buffer.from(key, 'base64'), }); + const [metadata] = await storage + .bucket(bucketName) + .file(fileName) + .getMetadata(); await file.save('secret data', {resumable: false}); const output = execSync( - `node changeFileCSEKToCMEK.js ${bucketName} ${encryptedFileName} ${key} ${kmsKeyName}` + `node changeFileCSEKToCMEK.js ${bucketName} ${encryptedFileName} ${key} ${kmsKeyName} ${metadata.generation}` ); assert.include( output, diff --git a/samples/system-test/files.test.js b/samples/system-test/files.test.js index a509ef256..ca4806bfc 100644 --- a/samples/system-test/files.test.js +++ b/samples/system-test/files.test.js @@ -43,6 +43,7 @@ const folderPath = path.join(cwd, 'resources'); const downloadFilePath = path.join(cwd, 'downloaded.txt'); const startByte = 0; const endByte = 20; +const doesNotExistPrecondition = 0; const fileContent = fs.readFileSync(filePath, 'utf-8'); @@ -61,7 +62,7 @@ describe('file', () => { it('should upload a file', async () => { const output = execSync( - `node uploadFile.js ${bucketName} ${filePath} ${fileName}` + `node uploadFile.js ${bucketName} ${filePath} ${fileName} ${doesNotExistPrecondition}` ); assert.match(output, new RegExp(`${filePath} uploaded to ${bucketName}`)); const [exists] = await bucket.file(fileName).exists(); @@ -84,7 +85,7 @@ describe('file', () => { it('should upload a file without authentication', async () => { const output = execSync( - `node uploadWithoutAuthentication.js ${bucketName} ${fileContents} ${fileName}` + `node uploadWithoutAuthentication.js ${bucketName} ${fileContents} ${fileName} ${doesNotExistPrecondition}` ); assert.match(output, new RegExp(`${fileName} uploaded to ${bucketName}`)); const [exists] = await bucket.file(fileName).exists(); @@ -110,8 +111,9 @@ describe('file', () => { }); it('should upload a file with a kms key', async () => { + const [metadata] = await bucket.file(fileName).getMetadata(); const output = execSync( - `node uploadFileWithKmsKey.js ${bucketName} ${filePath} ${kmsKeyName}` + `node uploadFileWithKmsKey.js ${bucketName} ${filePath} ${kmsKeyName} ${metadata.generation}` ); assert.include( output, @@ -219,7 +221,7 @@ describe('file', () => { it('should move a file', async () => { const output = execSync( - `node moveFile.js ${bucketName} ${fileName} ${movedFileName}` + `node moveFile.js ${bucketName} ${fileName} ${movedFileName} ${doesNotExistPrecondition}` ); assert.include( output, @@ -231,7 +233,7 @@ describe('file', () => { it('should copy a file', async () => { const output = execSync( - `node copyFile.js ${bucketName} ${movedFileName} ${bucketName} ${copiedFileName}` + `node copyFile.js ${bucketName} ${movedFileName} ${bucketName} ${copiedFileName} ${doesNotExistPrecondition}` ); assert.include( output, @@ -419,14 +421,16 @@ describe('file', () => { assert.include(output, `Name: ${copiedFileName}`); }); - it('should set metadata for a file', () => { + it('should set metadata for a file', async () => { + const [metadata] = await bucket.file(copiedFileName).getMetadata(); + // used in sample const userMetadata = { description: 'file description...', modified: '1900-01-01', }; const output = execSync( - `node fileSetMetadata.js ${bucketName} ${copiedFileName}` + `node fileSetMetadata.js ${bucketName} ${copiedFileName} ${metadata.generation} ` ); assert.match( @@ -438,7 +442,7 @@ describe('file', () => { it('should set storage class for a file', async () => { const output = execSync( - `node fileChangeStorageClass.js ${bucketName} ${copiedFileName} standard` + `node fileChangeStorageClass.js ${bucketName} ${copiedFileName} standard ${doesNotExistPrecondition}` ); assert.include(output, `${copiedFileName} has been set to standard`); const [metadata] = await storage @@ -477,8 +481,9 @@ describe('file', () => { }); it('should delete a file', async () => { + const [metadata] = await bucket.file(copiedFileName).getMetadata(); const output = execSync( - `node deleteFile.js ${bucketName} ${copiedFileName}` + `node deleteFile.js ${bucketName} ${copiedFileName} ${metadata.generation}` ); assert.match( output, diff --git a/samples/uploadEncryptedFile.js b/samples/uploadEncryptedFile.js index 10e25c3e8..8dd156cc0 100644 --- a/samples/uploadEncryptedFile.js +++ b/samples/uploadEncryptedFile.js @@ -17,7 +17,8 @@ function main( bucketName = 'my-bucket', filePath = path.join(__dirname, '../resources', 'test.txt'), destFileName = 'test.txt', - key = process.env.GOOGLE_CLOUD_KMS_KEY_US + key = process.env.GOOGLE_CLOUD_KMS_KEY_US, + generationMatchPrecondition = 0 ) { // [START storage_upload_encrypted_file] /** @@ -45,6 +46,15 @@ function main( const options = { destination: destFileName, encryptionKey: Buffer.from(key, 'base64'), + + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + preconditionOpts: {ifGenerationMatch: generationMatchPrecondition}, }; await storage.bucket(bucketName).upload(filePath, options); diff --git a/samples/uploadFile.js b/samples/uploadFile.js index 5cb56e8e8..1538e4ff1 100644 --- a/samples/uploadFile.js +++ b/samples/uploadFile.js @@ -15,7 +15,8 @@ function main( bucketName = 'my-bucket', filePath = './local/path/to/file.txt', - destFileName = 'file.txt' + destFileName = 'file.txt', + generationMatchPrecondition = 0 ) { // [START storage_upload_file] /** @@ -37,10 +38,19 @@ function main( const storage = new Storage(); async function uploadFile() { - await storage.bucket(bucketName).upload(filePath, { + const options = { destination: destFileName, - }); - + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + preconditionOpts: {ifGenerationMatch: generationMatchPrecondition}, + }; + + await storage.bucket(bucketName).upload(filePath, options); console.log(`${filePath} uploaded to ${bucketName}`); } diff --git a/samples/uploadFileWithKmsKey.js b/samples/uploadFileWithKmsKey.js index 8e2de5fd1..771638abc 100644 --- a/samples/uploadFileWithKmsKey.js +++ b/samples/uploadFileWithKmsKey.js @@ -23,7 +23,8 @@ function main( bucketName = 'my-bucket', filePath = 'test.txt', - kmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_US + kmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_US, + generationMatchPrecondition = 0 ) { // [START storage_upload_with_kms_key] /** @@ -45,9 +46,19 @@ function main( const storage = new Storage(); async function uploadFileWithKmsKey() { - await storage.bucket(bucketName).upload(filePath, { + const options = { kmsKeyName, - }); + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + preconditionOpts: {ifGenerationMatch: generationMatchPrecondition}, + }; + + await storage.bucket(bucketName).upload(filePath, options); console.log(`${filePath} uploaded to ${bucketName} using ${kmsKeyName}.`); } diff --git a/samples/uploadWithoutAuthentication.js b/samples/uploadWithoutAuthentication.js index 12922c4a3..f51e56940 100644 --- a/samples/uploadWithoutAuthentication.js +++ b/samples/uploadWithoutAuthentication.js @@ -15,7 +15,8 @@ function main( bucketName = 'my-bucket', contents = 'these are my file contents', - destFileName = 'file.txt' + destFileName = 'file.txt', + generationMatchPrecondition = 0 ) { // [START storage_upload_without_authentication] /** @@ -43,13 +44,24 @@ function main( // you can make requests without credentials. const [location] = await file.createResumableUpload(); //auth required - // Passes the location to file.save so you don't need to - // authenticate this call - await file.save(contents, { + const options = { uri: location, resumable: true, validation: false, - }); + + // Optional: + // Set a generation-match precondition to avoid potential race conditions + // and data corruptions. The request to upload is aborted if the object's + // generation number does not match your precondition. For a destination + // object that does not yet exist, set the ifGenerationMatch precondition to 0 + // If the destination object already exists in your bucket, set instead a + // generation-match precondition using its generation number. + preconditionOpts: {ifGenerationMatch: generationMatchPrecondition}, + }; + + // Passes the location to file.save so you don't need to + // authenticate this call + await file.save(contents, options); console.log(`${destFileName} uploaded to ${bucketName}`); }