From 576f3d75eede17b49877de7bfcb99faacbc5d4f7 Mon Sep 17 00:00:00 2001 From: Angel Caamal Date: Wed, 18 Mar 2026 23:33:40 +0000 Subject: [PATCH 1/2] feat(storage): introduce core bucket samples and tests for migration --- storage/addBucketLabel.js | 66 +++ storage/addBucketWebsiteConfiguration.js | 70 +++ storage/bucketMetadata.js | 53 ++ storage/changeDefaultStorageClass.js | 58 +++ storage/configureBucketCors.js | 83 +++ storage/createBucketWithDualRegion.js | 82 +++ .../createBucketWithHierarchicalNamespace.js | 68 +++ storage/createBucketWithObjectRetention.js | 61 +++ ...createBucketWithStorageClassAndLocation.js | 78 +++ storage/createBucketWithTurboReplication.js | 75 +++ storage/createNewBucket.js | 58 +++ storage/deleteBucket.js | 52 ++ storage/disableBucketVersioning.js | 57 ++ storage/disableSoftDelete.js | 56 ++ storage/disableUniformBucketLevelAccess.js | 63 +++ storage/enableBucketVersioning.js | 57 ++ storage/enableDefaultKMSKey.js | 68 +++ storage/enableUniformBucketLevelAccess.js | 63 +++ storage/getAutoclass.js | 58 +++ storage/getPublicAccessPrevention.js | 59 +++ storage/getRPO.js | 55 ++ storage/getSoftDeletePolicy.js | 65 +++ storage/getUniformBucketLevelAccess.js | 71 +++ storage/listBuckets.js | 44 ++ storage/makeBucketPublic.js | 53 ++ storage/package.json | 30 ++ storage/removeBucketCors.js | 53 ++ storage/removeBucketLabel.js | 58 +++ storage/removeDefaultKMSKey.js | 57 ++ storage/resources/.gitignore | 1 + storage/resources/resourcesSub1/testSub1.txt | 2 + storage/resources/test.txt | 1 + storage/resources/test2.txt | 1 + storage/scripts/cleanup | 44 ++ storage/setAutoclass.js | 64 +++ storage/setPublicAccessPreventionEnforced.js | 63 +++ storage/setPublicAccessPreventionInherited.js | 58 +++ storage/setRPOAsyncTurbo.js | 60 +++ storage/setRPODefault.js | 57 ++ storage/setSoftDeletePolicy.js | 56 ++ storage/system-test/buckets.test.js | 485 ++++++++++++++++++ ...t_9d800329-00da-4cdd-9a3e-7ac6743d5813.txt | 0 42 files changed, 2663 insertions(+) create mode 100644 storage/addBucketLabel.js create mode 100644 storage/addBucketWebsiteConfiguration.js create mode 100644 storage/bucketMetadata.js create mode 100644 storage/changeDefaultStorageClass.js create mode 100644 storage/configureBucketCors.js create mode 100644 storage/createBucketWithDualRegion.js create mode 100644 storage/createBucketWithHierarchicalNamespace.js create mode 100644 storage/createBucketWithObjectRetention.js create mode 100644 storage/createBucketWithStorageClassAndLocation.js create mode 100644 storage/createBucketWithTurboReplication.js create mode 100644 storage/createNewBucket.js create mode 100644 storage/deleteBucket.js create mode 100644 storage/disableBucketVersioning.js create mode 100644 storage/disableSoftDelete.js create mode 100644 storage/disableUniformBucketLevelAccess.js create mode 100644 storage/enableBucketVersioning.js create mode 100644 storage/enableDefaultKMSKey.js create mode 100644 storage/enableUniformBucketLevelAccess.js create mode 100644 storage/getAutoclass.js create mode 100644 storage/getPublicAccessPrevention.js create mode 100644 storage/getRPO.js create mode 100644 storage/getSoftDeletePolicy.js create mode 100644 storage/getUniformBucketLevelAccess.js create mode 100644 storage/listBuckets.js create mode 100644 storage/makeBucketPublic.js create mode 100644 storage/package.json create mode 100644 storage/removeBucketCors.js create mode 100644 storage/removeBucketLabel.js create mode 100644 storage/removeDefaultKMSKey.js create mode 100644 storage/resources/.gitignore create mode 100644 storage/resources/resourcesSub1/testSub1.txt create mode 100644 storage/resources/test.txt create mode 100644 storage/resources/test2.txt create mode 100644 storage/scripts/cleanup create mode 100644 storage/setAutoclass.js create mode 100644 storage/setPublicAccessPreventionEnforced.js create mode 100644 storage/setPublicAccessPreventionInherited.js create mode 100644 storage/setRPOAsyncTurbo.js create mode 100644 storage/setRPODefault.js create mode 100644 storage/setSoftDeletePolicy.js create mode 100644 storage/system-test/buckets.test.js create mode 100644 storage/system-test/test_9d800329-00da-4cdd-9a3e-7ac6743d5813.txt diff --git a/storage/addBucketLabel.js b/storage/addBucketLabel.js new file mode 100644 index 0000000000..996c20bb03 --- /dev/null +++ b/storage/addBucketLabel.js @@ -0,0 +1,66 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Add Bucket Label. +// description: Adds bucket label. +// usage: node addBucketLabel.js + +function main( + bucketName = 'my-bucket', + labelKey = 'labelone', + labelValue = 'labelonevalue' +) { + // [START storage_add_bucket_label] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The key of the label to add + // const labelKey = 'label-key-to-add'; + + // The value of the label to add + // const labelValue = 'label-value-to-add'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + const labels = { + [labelKey]: labelValue, + }; + + async function addBucketLabel() { + try { + await storage.bucket(bucketName).setMetadata({labels}); + console.log(`Added label to bucket ${bucketName}`); + } catch (error) { + console.error( + 'Error executing add bucket label:', + error.message || error + ); + } + } + + addBucketLabel(); + // [END storage_add_bucket_label] +} + +main(...process.argv.slice(2)); diff --git a/storage/addBucketWebsiteConfiguration.js b/storage/addBucketWebsiteConfiguration.js new file mode 100644 index 0000000000..1d008b9443 --- /dev/null +++ b/storage/addBucketWebsiteConfiguration.js @@ -0,0 +1,70 @@ +// Copyright 2021 Google LLC +// +// 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'; + +// sample-metadata: +// title: Bucket Website Configuration. +// description: Bucket Website Configuration. +// usage: node addBucketWebsiteConfiguration.js + +function main( + bucketName = 'my-bucket', + mainPageSuffix = 'http://example.com', + notFoundPage = 'http://example.com/404.html' +) { + // [START storage_define_bucket_website_configuration] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The name of the main page + // const mainPageSuffix = 'http://example.com'; + + // The Name of a 404 page + // const notFoundPage = 'http://example.com/404.html'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function addBucketWebsiteConfiguration() { + try { + await storage.bucket(bucketName).setMetadata({ + website: { + mainPageSuffix, + notFoundPage, + }, + }); + + console.log( + `Static website bucket ${bucketName} is set up to use ${mainPageSuffix} as the index page and ${notFoundPage} as the 404 page` + ); + } catch (error) { + console.error( + 'Error executing add bucket website configuration:', + error.message || error + ); + } + } + + addBucketWebsiteConfiguration(); + // [END storage_define_bucket_website_configuration] +} + +main(...process.argv.slice(2)); diff --git a/storage/bucketMetadata.js b/storage/bucketMetadata.js new file mode 100644 index 0000000000..399354e0b2 --- /dev/null +++ b/storage/bucketMetadata.js @@ -0,0 +1,53 @@ +// Copyright 2019 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Get Bucket Metadata. +// description: Get bucket metadata. +// usage: node bucketMetadata.js + +function main(bucketName = 'my-bucket') { + // [START storage_get_bucket_metadata] + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function getBucketMetadata() { + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Get Bucket Metadata + try { + const [metadata] = await storage.bucket(bucketName).getMetadata(); + + console.log(JSON.stringify(metadata, null, 2)); + } catch (error) { + console.error( + 'Error executing get bucket metadata:', + error.message || error + ); + } + } + // [END storage_get_bucket_metadata] + getBucketMetadata(); +} + +main(...process.argv.slice(2)); diff --git a/storage/changeDefaultStorageClass.js b/storage/changeDefaultStorageClass.js new file mode 100644 index 0000000000..3177b62b99 --- /dev/null +++ b/storage/changeDefaultStorageClass.js @@ -0,0 +1,58 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Change Bucket's Default Storage Class. +// description: Change Bucket's Default Storage Class. +// usage: node changeDefaultStorageClass.js + +function main(bucketName = 'my-bucket', storageClass = 'standard') { + // [START storage_change_default_storage_class] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The name of a storage class + // See the StorageClass documentation for other valid storage classes: + // https://googleapis.dev/java/google-cloud-clients/latest/com/google/cloud/storage/StorageClass.html + // const storageClass = 'coldline'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function changeDefaultStorageClass() { + try { + await storage.bucket(bucketName).setStorageClass(storageClass); + + console.log(`${bucketName} has been set to ${storageClass}`); + } catch (error) { + console.error( + 'Error executing change default storage class:', + error.message || error + ); + } + } + + changeDefaultStorageClass(); + // [END storage_change_default_storage_class] +} + +main(...process.argv.slice(2)); diff --git a/storage/configureBucketCors.js b/storage/configureBucketCors.js new file mode 100644 index 0000000000..7b07771c22 --- /dev/null +++ b/storage/configureBucketCors.js @@ -0,0 +1,83 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Configure Bucket Cors. +// description: Configures bucket cors. +// usage: node configureBucketCors.js + +function main( + bucketName = 'my-bucket', + maxAgeSeconds = 3600, + method = 'POST', + origin = 'http://example.appspot.com', + responseHeader = 'content-type' +) { + // [START storage_cors_configuration] + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The origin for this CORS config to allow requests from + // const origin = 'http://example.appspot.com'; + + // The response header to share across origins + // const responseHeader = 'Content-Type'; + + // The maximum amount of time the browser can make requests before it must + // repeat preflighted requests + // const maxAgeSeconds = 3600; + + // The name of the method + // See the HttpMethod documentation for other HTTP methods available: + // https://cloud.google.com/appengine/docs/standard/java/javadoc/com/google/appengine/api/urlfetch/HTTPMethod + // const method = 'GET'; + + async function configureBucketCors() { + try { + await storage.bucket(bucketName).setCorsConfiguration([ + { + maxAgeSeconds, + method: [method], + origin: [origin], + responseHeader: [responseHeader], + }, + ]); + + console.log(`Bucket ${bucketName} was updated with a CORS config + to allow ${method} requests from ${origin} sharing + ${responseHeader} responses across origins`); + } catch (error) { + console.error( + 'Error executing configure bucket cors:', + error.message || error + ); + } + } + + configureBucketCors(); + // [END storage_cors_configuration] +} + +main(...process.argv.slice(2)); diff --git a/storage/createBucketWithDualRegion.js b/storage/createBucketWithDualRegion.js new file mode 100644 index 0000000000..250208b471 --- /dev/null +++ b/storage/createBucketWithDualRegion.js @@ -0,0 +1,82 @@ +/** + * Copyright 2022 Google LLC + * + * 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'; + +// sample-metadata: +// title: Create a Dual-Region Bucket +// description: Create a Dual-Region Bucket with provided location and regions. +// usage: node createBucketWithDualRegion.js + +function main( + bucketName = 'my-bucket', + location = 'US', + region1 = 'US-EAST1', + region2 = 'US-WEST1' +) { + // [START storage_create_bucket_dual_region] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The bucket's pair of regions. Case-insensitive. + // See this documentation for other valid locations: + // https://cloud.google.com/storage/docs/locations + // const location = 'US'; + // const region1 = 'US-EAST1'; + // const region2 = 'US-WEST1'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + // The bucket in the sample below will be created in the project associated with this client. + // For more information, please see https://cloud.google.com/docs/authentication/production or https://googleapis.dev/nodejs/storage/latest/Storage.html + const storage = new Storage(); + + async function createDualRegionBucket() { + // For regions supporting dual-regions see: https://cloud.google.com/storage/docs/locations + try { + const [bucket] = await storage.createBucket(bucketName, { + location, + customPlacementConfig: { + dataLocations: [region1, region2], + }, + }); + + console.log(`Created '${bucket.name}'`); + console.log(`- location: '${bucket.metadata.location}'`); + console.log(`- locationType: '${bucket.metadata.locationType}'`); + console.log( + `- customPlacementConfig: '${JSON.stringify( + bucket.metadata.customPlacementConfig + )}'` + ); + } catch (error) { + console.error( + 'Error executing create dual region bucket:', + error.message || error + ); + } + } + + createDualRegionBucket(); + // [END storage_create_bucket_dual_region] +} + +main(...process.argv.slice(2)); diff --git a/storage/createBucketWithHierarchicalNamespace.js b/storage/createBucketWithHierarchicalNamespace.js new file mode 100644 index 0000000000..fdada6eb17 --- /dev/null +++ b/storage/createBucketWithHierarchicalNamespace.js @@ -0,0 +1,68 @@ +/** + * Copyright 2024 Google LLC + * + * 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'; + +// sample-metadata: +// title: Create a hierarchical namespace enabled bucket +// description: Create a hierarchical namespace enabled bucket. +// usage: node createBucketWithHierarchicalNamespace.js + +function main(bucketName = 'my-bucket') { + // [START storage_create_bucket_hierarchical_namespace] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + // The bucket in the sample below will be created in the project associated with this client. + // For more information, please see https://cloud.google.com/docs/authentication/production or https://googleapis.dev/nodejs/storage/latest/Storage.html + const storage = new Storage(); + + async function createBucketWithHierarchicalNamespace() { + try { + const [bucket] = await storage.createBucket(bucketName, { + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: true, + }, + }, + hierarchicalNamespace: { + enabled: true, + }, + }); + + console.log( + `Created '${bucket.name}' with hierarchical namespace enabled.` + ); + } catch (error) { + console.error( + 'Error executing create bucket with hierarchical namespace:', + error.message || error + ); + } + } + + createBucketWithHierarchicalNamespace(); + // [END storage_create_bucket_hierarchical_namespace] +} + +main(...process.argv.slice(2)); diff --git a/storage/createBucketWithObjectRetention.js b/storage/createBucketWithObjectRetention.js new file mode 100644 index 0000000000..5624ed834b --- /dev/null +++ b/storage/createBucketWithObjectRetention.js @@ -0,0 +1,61 @@ +/** + * Copyright 2024 Google LLC + * + * 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'; + +// sample-metadata: +// title: Create a Bucket with object retention enabled. +// description: Create a Bucket with object retention enabled. +// usage: node createBucketWithObjectRetention.js + +function main(bucketName = 'my-bucket') { + // [START storage_create_bucket_with_object_retention] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + // The bucket in the sample below will be created in the project associated with this client. + // For more information, please see https://cloud.google.com/docs/authentication/production or https://googleapis.dev/nodejs/storage/latest/Storage.html + const storage = new Storage(); + + async function createBucketWithObjectRetention() { + try { + const [bucket] = await storage.createBucket(bucketName, { + enableObjectRetention: true, + }); + + console.log( + `Created '${bucket.name}' with object retention enabled setting: ${bucket.metadata.objectRetention.mode}` + ); + } catch (error) { + console.error( + 'Error executing create bucket with object retention:', + error.message || error + ); + } + } + + createBucketWithObjectRetention(); + // [END storage_create_bucket_with_object_retention] +} + +main(...process.argv.slice(2)); diff --git a/storage/createBucketWithStorageClassAndLocation.js b/storage/createBucketWithStorageClassAndLocation.js new file mode 100644 index 0000000000..3db0a531bc --- /dev/null +++ b/storage/createBucketWithStorageClassAndLocation.js @@ -0,0 +1,78 @@ +/** + * Copyright 2020 Google LLC + * + * 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'; + +// sample-metadata: +// title: Create Bucket With Storage Class and Location. +// description: Create Bucket With Storage Class and Location. +// usage: node createBucketWithStorageClassAndLocation.js + +function main( + bucketName = 'my-bucket', + storageClass = 'coldline', + location = 'ASIA' +) { + // [START storage_create_bucket_class_location] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The name of a storage class + // See the StorageClass documentation for other valid storage classes: + // https://googleapis.dev/java/google-cloud-clients/latest/com/google/cloud/storage/StorageClass.html + // const storageClass = 'coldline'; + + // The name of a location + // See this documentation for other valid locations: + // http://g.co/cloud/storage/docs/locations#location-mr + // const location = 'ASIA'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + // The bucket in the sample below will be created in the project associated with this client. + // For more information, please see https://cloud.google.com/docs/authentication/production or https://googleapis.dev/nodejs/storage/latest/Storage.html + const storage = new Storage(); + + async function createBucketWithStorageClassAndLocation() { + // For default values see: https://cloud.google.com/storage/docs/locations and + // https://cloud.google.com/storage/docs/storage-classes + try { + const [bucket] = await storage.createBucket(bucketName, { + location, + [storageClass]: true, + }); + + console.log( + `${bucket.name} created with ${storageClass} class in ${location}` + ); + } catch (error) { + console.error( + 'Error executing create bucket with storage class and location:', + error.message || error + ); + } + } + + createBucketWithStorageClassAndLocation(); + // [END storage_create_bucket_class_location] +} + +main(...process.argv.slice(2)); diff --git a/storage/createBucketWithTurboReplication.js b/storage/createBucketWithTurboReplication.js new file mode 100644 index 0000000000..6d666271ae --- /dev/null +++ b/storage/createBucketWithTurboReplication.js @@ -0,0 +1,75 @@ +/** + * Copyright 2022 Google LLC + * + * 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 main(bucketName = 'my-bucket', location = 'NAM4') { + // [START storage_create_bucket_turbo_replication] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The name of a dual-region location + // See this documentation for other valid locations: + // https://cloud.google.com/storage/docs/locations#location-dr + // const location = 'NAM4'; + + // Flag to enable turbo replication for this bucket + const rpo = 'ASYNC_TURBO'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + // The bucket in the sample below will be created in the project associated with this client. + // For more information, please see https://cloud.google.com/docs/authentication/production or https://googleapis.dev/nodejs/storage/latest/Storage.html + const storage = new Storage(); + + async function createBucketWithTurboReplication() { + // For default values see: https://cloud.google.com/storage/docs/locations and + // https://cloud.google.com/storage/docs/storage-classes + try { + const [bucket] = await storage.createBucket(bucketName, { + location, + rpo, + }); + + console.log( + `${bucket.name} created with the recovery point objective (RPO) set to ${rpo} in ${location}.` + ); + } catch (error) { + console.error( + 'Error executing create bucket with turbo replication:', + error.message || error + ); + } + } + + createBucketWithTurboReplication(); + // [END storage_create_bucket_turbo_replication] +} + +main(...process.argv.slice(2)); diff --git a/storage/createNewBucket.js b/storage/createNewBucket.js new file mode 100644 index 0000000000..9b640b0886 --- /dev/null +++ b/storage/createNewBucket.js @@ -0,0 +1,58 @@ +/** + * Copyright 2019 Google LLC + * + * 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'; + +function main(bucketName = 'my-bucket') { + // [START storage_create_bucket] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + // The bucket in the sample below will be created in the project associated with this client. + // For more information, please see https://cloud.google.com/docs/authentication/production or https://googleapis.dev/nodejs/storage/latest/Storage.html + const storage = new Storage(); + + async function createBucket() { + // Creates a new bucket in the Asia region with the coldline default storage + // class. Leave the second argument blank for default settings. + // + // For default values see: https://cloud.google.com/storage/docs/locations and + // https://cloud.google.com/storage/docs/storage-classes + + try { + const [bucket] = await storage.createBucket(bucketName, { + location: 'ASIA', + storageClass: 'COLDLINE', + }); + + console.log(`Bucket ${bucket.name} created.`); + } catch (error) { + console.error('Error executing create bucket:', error.message || error); + } + } + + createBucket(); + // [END storage_create_bucket] +} + +main(...process.argv.slice(2)); diff --git a/storage/deleteBucket.js b/storage/deleteBucket.js new file mode 100644 index 0000000000..0b08732e8f --- /dev/null +++ b/storage/deleteBucket.js @@ -0,0 +1,52 @@ +// Copyright 2020 Google LLC +// +// 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'; + +/** + * 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. + */ + +function main(bucketName = 'my-bucket') { + // [START storage_delete_bucket] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function deleteBucket() { + try { + await storage.bucket(bucketName).delete(); + console.log(`Bucket ${bucketName} deleted`); + } catch (error) { + console.error('Error executing delete bucket:', error.message || error); + } + } + + deleteBucket(); + // [END storage_delete_bucket] +} + +main(...process.argv.slice(2)); diff --git a/storage/disableBucketVersioning.js b/storage/disableBucketVersioning.js new file mode 100644 index 0000000000..a603c0c82d --- /dev/null +++ b/storage/disableBucketVersioning.js @@ -0,0 +1,57 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Disable Bucket Versioning. +// description: Disables bucket versioning. +// usage: node disableBucketVersioning.js + +function main(bucketName = 'my-bucket') { + // [START storage_disable_versioning] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function disableBucketVersioning() { + try { + await storage.bucket(bucketName).setMetadata({ + versioning: { + enabled: false, + }, + }); + + console.log(`Versioning is disabled for bucket ${bucketName}`); + } catch (error) { + console.error( + 'Error executing disable bucket versioning:', + error.message || error + ); + } + } + + disableBucketVersioning(); + // [END storage_disable_versioning] +} + +main(...process.argv.slice(2)); diff --git a/storage/disableSoftDelete.js b/storage/disableSoftDelete.js new file mode 100644 index 0000000000..a65aba4462 --- /dev/null +++ b/storage/disableSoftDelete.js @@ -0,0 +1,56 @@ +/** + * Copyright 2025 Google LLC + * + * 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'; + +function main(bucketName = 'my-bucket') { + // [START storage_disable_soft_delete] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function disableSoftDelete() { + try { + const options = { + softDeletePolicy: { + retentionDurationSeconds: 0, + }, + }; + + const [metadata] = await storage.bucket(bucketName).setMetadata(options); + + console.log(`Bucket ${metadata.name} soft delete policy was disabled`); + } catch (error) { + console.error( + 'Error executing disable soft delete:', + error.message || error + ); + } + } + + disableSoftDelete(); + // [END storage_disable_soft_delete] +} + +main(...process.argv.slice(2)); diff --git a/storage/disableUniformBucketLevelAccess.js b/storage/disableUniformBucketLevelAccess.js new file mode 100644 index 0000000000..1b80c0b594 --- /dev/null +++ b/storage/disableUniformBucketLevelAccess.js @@ -0,0 +1,63 @@ +// Copyright 2020 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_disable_uniform_bucket_level_access] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + async function disableUniformBucketLevelAccess() { + // Disables uniform bucket-level access for the bucket + try { + await storage.bucket(bucketName).setMetadata({ + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: false, + }, + }, + }); + + console.log( + `Uniform bucket-level access was disabled for ${bucketName}.` + ); + } catch (error) { + console.error( + 'Error executing disable uniform bucket-level access:', + error.message || error + ); + } + } + + disableUniformBucketLevelAccess(); + // [END storage_disable_uniform_bucket_level_access] +} +main(...process.argv.slice(2)); diff --git a/storage/enableBucketVersioning.js b/storage/enableBucketVersioning.js new file mode 100644 index 0000000000..f95fb73507 --- /dev/null +++ b/storage/enableBucketVersioning.js @@ -0,0 +1,57 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Enable Bucket Versioning. +// description: Enables bucket versioning. +// usage: node enableBucketVersioning.js + +function main(bucketName = 'my-bucket') { + // [START storage_enable_versioning] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function enableBucketVersioning() { + try { + await storage.bucket(bucketName).setMetadata({ + versioning: { + enabled: true, + }, + }); + + console.log(`Versioning is enabled for bucket ${bucketName}`); + } catch (error) { + console.error( + 'Error executing enable bucket versioning:', + error.message || error + ); + } + } + + enableBucketVersioning(); + // [END storage_enable_versioning] +} + +main(...process.argv.slice(2)); diff --git a/storage/enableDefaultKMSKey.js b/storage/enableDefaultKMSKey.js new file mode 100644 index 0000000000..9d1eef7590 --- /dev/null +++ b/storage/enableDefaultKMSKey.js @@ -0,0 +1,68 @@ +// Copyright 2020 Google LLC +// +// 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 main( + bucketName = 'my-bucket', + defaultKmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_ASIA +) { + // [START storage_set_bucket_default_kms_key] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The name of the KMS-key to use as a default + // const defaultKmsKeyName = 'my-key'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function enableDefaultKMSKey() { + try { + await storage.bucket(bucketName).setMetadata({ + encryption: { + defaultKmsKeyName, + }, + }); + + console.log( + `Default KMS key for ${bucketName} was set to ${defaultKmsKeyName}.` + ); + } catch (error) { + console.error( + 'Error executing enable default KMS key:', + error.message || error + ); + } + } + + enableDefaultKMSKey(); + // [END storage_set_bucket_default_kms_key] +} + +main(...process.argv.slice(2)); diff --git a/storage/enableUniformBucketLevelAccess.js b/storage/enableUniformBucketLevelAccess.js new file mode 100644 index 0000000000..828fdf0247 --- /dev/null +++ b/storage/enableUniformBucketLevelAccess.js @@ -0,0 +1,63 @@ +// Copyright 2020 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_enable_uniform_bucket_level_access] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + // Enables uniform bucket-level access for the bucket + async function enableUniformBucketLevelAccess() { + try { + await storage.bucket(bucketName).setMetadata({ + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: true, + }, + }, + }); + + console.log(`Uniform bucket-level access was enabled for ${bucketName}.`); + } catch (error) { + console.error( + 'Error executing enable uniform bucket-level access:', + error.message || error + ); + } + } + + enableUniformBucketLevelAccess(); + // [END storage_enable_uniform_bucket_level_access] +} + +main(...process.argv.slice(2)); diff --git a/storage/getAutoclass.js b/storage/getAutoclass.js new file mode 100644 index 0000000000..55cf523b87 --- /dev/null +++ b/storage/getAutoclass.js @@ -0,0 +1,58 @@ +// Copyright 2022 Google LLC +// +// 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 files 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 main(bucketName = 'my-bucket') { + // [START storage_get_autoclass] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function getAutoclass() { + try { + const [metadata] = await storage.bucket(bucketName).getMetadata(); + console.log( + `Autoclass is ${ + metadata.autoclass.enabled ? 'enabled' : 'disabled' + } for ${metadata.name} at ${metadata.autoclass.toggleTime}. + Autoclass terminal storage class is last updated to ${ + metadata.autoclass.terminalStorageClass + } at ${metadata.autoclass.terminalStorageClassUpdateTime}.` + ); + } catch (error) { + console.error('Error executing get autoclass:', error.message || error); + } + } + + getAutoclass(); + // [END storage_get_autoclass] +} +main(...process.argv.slice(2)); diff --git a/storage/getPublicAccessPrevention.js b/storage/getPublicAccessPrevention.js new file mode 100644 index 0000000000..e782ed529e --- /dev/null +++ b/storage/getPublicAccessPrevention.js @@ -0,0 +1,59 @@ +// Copyright 2021 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_get_public_access_prevention] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The name of your GCS bucket + // const bucketName = 'Name of a bucket, e.g. my-bucket'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function getPublicAccessPrevention() { + // Gets Bucket Metadata and prints publicAccessPrevention value (either 'inherited' or 'enforced'). + try { + const [metadata] = await storage.bucket(bucketName).getMetadata(); + console.log( + `Public access prevention is ${metadata.iamConfiguration.publicAccessPrevention} for ${bucketName}.` + ); + } catch (error) { + console.error( + 'Error executing get public access prevention:', + error.message || error + ); + } + } + + getPublicAccessPrevention(); + + // [END storage_get_public_access_prevention] +} + +main(...process.argv.slice(2)); diff --git a/storage/getRPO.js b/storage/getRPO.js new file mode 100644 index 0000000000..94f54a9675 --- /dev/null +++ b/storage/getRPO.js @@ -0,0 +1,55 @@ +// Copyright 2022 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_get_rpo] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The name of your GCS bucket in a dual-region + // const bucketName = 'Name of a bucket, e.g. my-bucket'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function getRPO() { + // Gets Bucket Metadata and prints RPO value (either 'default' or 'async_turbo'). + // If RPO is undefined, the bucket is a single region bucket + try { + const [metadata] = await storage.bucket(bucketName).getMetadata(); + console.log(`RPO is ${metadata.rpo} for ${bucketName}.`); + } catch (error) { + console.error('Error executing get RPO:', error.message || error); + } + } + + getRPO(); + + // [END storage_get_rpo] +} + +main(...process.argv.slice(2)); diff --git a/storage/getSoftDeletePolicy.js b/storage/getSoftDeletePolicy.js new file mode 100644 index 0000000000..b7be0acd39 --- /dev/null +++ b/storage/getSoftDeletePolicy.js @@ -0,0 +1,65 @@ +/** + * Copyright 2025 Google LLC + * + * 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'; + +function main(bucketName = 'my-bucket') { + // [START storage_get_soft_delete_policy] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function getSoftDeletePolicy() { + try { + const [metadata] = await storage.bucket(bucketName).getMetadata(); + + const softDelete = metadata.softDeletePolicy; + if ( + !softDelete || + !softDelete.retentionDurationSeconds || + softDelete.retentionDurationSeconds === '0' + ) { + console.log(`Bucket ${metadata.name} soft delete policy was disabled`); + } else { + console.log(`Soft delete policy for ${metadata.name}`); + console.log( + `Soft delete Period: ${softDelete.retentionDurationSeconds} seconds` + ); + if (softDelete.effectiveTime) { + console.log(`Effective Time: ${softDelete.effectiveTime}`); + } + } + } catch (error) { + console.error( + 'Error executing get soft delete policy:', + error.message || error + ); + } + } + + getSoftDeletePolicy(); + // [END storage_get_soft_delete_policy] +} + +main(...process.argv.slice(2)); diff --git a/storage/getUniformBucketLevelAccess.js b/storage/getUniformBucketLevelAccess.js new file mode 100644 index 0000000000..ff4dddce82 --- /dev/null +++ b/storage/getUniformBucketLevelAccess.js @@ -0,0 +1,71 @@ +// Copyright 2020 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_get_uniform_bucket_level_access] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function getUniformBucketLevelAccess() { + // Gets Bucket Metadata and checks if uniform bucket-level access is enabled. + try { + const [metadata] = await storage.bucket(bucketName).getMetadata(); + + if (metadata.iamConfiguration) { + const uniformBucketLevelAccess = + metadata.iamConfiguration.uniformBucketLevelAccess; + console.log( + `Uniform bucket-level access is enabled for ${bucketName}.` + ); + console.log( + `Bucket will be locked on ${uniformBucketLevelAccess.lockedTime}.` + ); + } else { + console.log( + `Uniform bucket-level access is not enabled for ${bucketName}.` + ); + } + } catch (error) { + console.error( + 'Error executing get uniform bucket-level access:', + error.message || error + ); + } + } + + getUniformBucketLevelAccess(); + + // [END storage_get_uniform_bucket_level_access] +} + +main(...process.argv.slice(2)); diff --git a/storage/listBuckets.js b/storage/listBuckets.js new file mode 100644 index 0000000000..033495b909 --- /dev/null +++ b/storage/listBuckets.js @@ -0,0 +1,44 @@ +/** + * Copyright 2020 Google LLC + * + * 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'; + +function main() { + // [START storage_list_buckets] + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function listBuckets() { + try { + const [buckets] = await storage.getBuckets(); + + console.log('Buckets:'); + buckets.forEach(bucket => { + console.log(bucket.name); + }); + } catch (error) { + console.error('Error executing list buckets:', error.message || error); + } + } + + listBuckets(); + // [END storage_list_buckets] +} + +main(...process.argv.slice(2)); diff --git a/storage/makeBucketPublic.js b/storage/makeBucketPublic.js new file mode 100644 index 0000000000..2a8166113f --- /dev/null +++ b/storage/makeBucketPublic.js @@ -0,0 +1,53 @@ +// Copyright 2021 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Make Bucket Public. +// description: Storage Make Bucket Public. +// usage: node makeBucketPublic.js + +function main(bucketName = 'my-bucket') { + // [START storage_set_bucket_public_iam] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function makeBucketPublic() { + try { + await storage.bucket(bucketName).makePublic(); + + console.log(`Bucket ${bucketName} is now publicly readable`); + } catch (error) { + console.error( + 'Error executing make bucket public:', + error.message || error + ); + } + } + + makeBucketPublic(); + // [END storage_set_bucket_public_iam] +} + +main(...process.argv.slice(2)); diff --git a/storage/package.json b/storage/package.json new file mode 100644 index 0000000000..71acc18ab5 --- /dev/null +++ b/storage/package.json @@ -0,0 +1,30 @@ +{ + "name": "@google-cloud/storage-samples", + "description": "Samples for the Cloud Storage Client Library for Node.js.", + "license": "Apache-2.0", + "author": "Google Inc.", + "engines": { + "node": ">=12" + }, + "repository": "googleapis/nodejs-storage", + "private": true, + "files": [ + "*.js" + ], + "scripts": { + "cleanup": "node scripts/cleanup", + "test": "mocha system-test/*.js --timeout 800000" + }, + "dependencies": { + "@google-cloud/pubsub": "^4.0.0", + "@google-cloud/storage": "^7.19.0", + "node-fetch": "^2.6.7", + "uuid": "^8.0.0", + "yargs": "^16.0.0" + }, + "devDependencies": { + "chai": "^4.2.0", + "mocha": "^8.0.0", + "p-limit": "^3.1.0" + } +} diff --git a/storage/removeBucketCors.js b/storage/removeBucketCors.js new file mode 100644 index 0000000000..cbbc02d762 --- /dev/null +++ b/storage/removeBucketCors.js @@ -0,0 +1,53 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Remove Bucket Cors Configuration. +// description: Removes bucket cors configuration. +// usage: node removeBucketCors.js + +function main(bucketName = 'my-bucket') { + // [START storage_remove_cors_configuration] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function removeBucketCors() { + try { + await storage.bucket(bucketName).setCorsConfiguration([]); + + console.log(`Removed CORS configuration from bucket ${bucketName}`); + } catch (error) { + console.error( + 'Error executing remove bucket cors:', + error.message || error + ); + } + } + + removeBucketCors(); + // [END storage_remove_cors_configuration] +} + +main(...process.argv.slice(2)); diff --git a/storage/removeBucketLabel.js b/storage/removeBucketLabel.js new file mode 100644 index 0000000000..fc6d0023ec --- /dev/null +++ b/storage/removeBucketLabel.js @@ -0,0 +1,58 @@ +// Copyright 2020 Google LLC +// +// 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'; + +// sample-metadata: +// title: Storage Remove Bucket Label. +// description: Removes bucket label. +// usage: node removeBucketLabel.js ) + +function main(bucketName = 'my-bucket', labelKey = 'labelone') { + // [START storage_remove_bucket_label] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The key of the label to remove from the bucket + // const labelKey = 'label-key-to-remove'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function removeBucketLabel() { + try { + const labels = {}; + // To remove a label set the value of the key to null. + labels[labelKey] = null; + await storage.bucket(bucketName).setMetadata({labels}); + console.log(`Removed labels from bucket ${bucketName}`); + } catch (error) { + console.error( + 'Error executing remove bucket label:', + error.message || error + ); + } + } + + removeBucketLabel(); + // [END storage_remove_bucket_label] +} + +main(...process.argv.slice(2)); diff --git a/storage/removeDefaultKMSKey.js b/storage/removeDefaultKMSKey.js new file mode 100644 index 0000000000..ec32d59ecc --- /dev/null +++ b/storage/removeDefaultKMSKey.js @@ -0,0 +1,57 @@ +// Copyright 2021 Google LLC +// +// 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'; + +// sample-metadata: +// title: Remove Default KMS Key. +// description: Remove Default KMS Key. +// usage: node removeDefaultKMSKey.js + +function main(bucketName = 'my-bucket') { + // [START storage_bucket_delete_default_kms_key] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function removeDefaultKMSKey() { + try { + await storage.bucket(bucketName).setMetadata({ + encryption: { + defaultKmsKeyName: null, + }, + }); + + console.log(`Default KMS key was removed from ${bucketName}`); + } catch (error) { + console.error( + 'Error executing remove default KMS key:', + error.message || error + ); + } + } + + removeDefaultKMSKey(); + // [END storage_bucket_delete_default_kms_key] +} + +main(...process.argv.slice(2)); diff --git a/storage/resources/.gitignore b/storage/resources/.gitignore new file mode 100644 index 0000000000..6738013702 --- /dev/null +++ b/storage/resources/.gitignore @@ -0,0 +1 @@ +downloaded.txt diff --git a/storage/resources/resourcesSub1/testSub1.txt b/storage/resources/resourcesSub1/testSub1.txt new file mode 100644 index 0000000000..51f4b307d5 --- /dev/null +++ b/storage/resources/resourcesSub1/testSub1.txt @@ -0,0 +1,2 @@ +Sub1 +Hello World! \ No newline at end of file diff --git a/storage/resources/test.txt b/storage/resources/test.txt new file mode 100644 index 0000000000..c57eff55eb --- /dev/null +++ b/storage/resources/test.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/storage/resources/test2.txt b/storage/resources/test2.txt new file mode 100644 index 0000000000..010302410b --- /dev/null +++ b/storage/resources/test2.txt @@ -0,0 +1 @@ +Hello World 2! \ No newline at end of file diff --git a/storage/scripts/cleanup b/storage/scripts/cleanup new file mode 100644 index 0000000000..61bd73114f --- /dev/null +++ b/storage/scripts/cleanup @@ -0,0 +1,44 @@ +#!/usr/bin/env node + +// Copyright 2019 Google LLC +// +// 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 {Storage} = require('@google-cloud/storage'); +const storage = new Storage(); +const NAME_REG_EXP = /^nodejs-storage-samples-[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/; + +storage + .getBuckets() + .then(([buckets]) => { + let promise = Promise.resolve(); + + buckets + .filter((bucket) => NAME_REG_EXP.test(bucket.name)) + .forEach((bucket) => { + promise = promise.then(() => { + return bucket.deleteFiles() + .then(() => bucket.deleteFiles(), console.error) + .then(() => { + console.log(`Deleting ${bucket.name}`); + return bucket.delete(); + }, console.error) + .catch(console.error); + }); + }); + }) + .catch((err) => { + console.error('ERROR:', err); + }); diff --git a/storage/setAutoclass.js b/storage/setAutoclass.js new file mode 100644 index 0000000000..e6c8f16027 --- /dev/null +++ b/storage/setAutoclass.js @@ -0,0 +1,64 @@ +/** + * Copyright 2022 Google LLC + * + * 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'; + +function main( + bucketName = 'my-bucket', + toggle = true, + terminalStorageClass = 'ARCHIVE' +) { + // [START storage_set_autoclass] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // The terminal storage class to be set on your GCS bucket. Valid values are NEARLINE and ARCHIVE. + // const terminalStorageClass = 'NEARLINE'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function setAutoclass() { + // Configure the Autoclass setting for a bucket. + // terminalStorageClass field is optional and defaults to NEARLINE if not otherwise specified. + // Valid terminalStorageClass values are NEARLINE and ARCHIVE. + try { + const [metadata] = await storage.bucket(bucketName).setMetadata({ + autoclass: { + enabled: toggle, + terminalStorageClass, + }, + }); + + console.log( + `Autoclass terminal storage class is ${metadata.autoclass.terminalStorageClass}.` + ); + } catch (error) { + console.error('Error executing set autoclass:', error.message || error); + } + } + + setAutoclass(); + // [END storage_set_autoclass] +} + +main(...process.argv.slice(2)); diff --git a/storage/setPublicAccessPreventionEnforced.js b/storage/setPublicAccessPreventionEnforced.js new file mode 100644 index 0000000000..71885230dd --- /dev/null +++ b/storage/setPublicAccessPreventionEnforced.js @@ -0,0 +1,63 @@ +// Copyright 2021 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_set_public_access_prevention_enforced] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The name of your GCS bucket + // const bucketName = 'Name of a bucket, e.g. my-bucket'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + // Enforces public access prevention for the bucket + async function setPublicAccessPreventionEnforced() { + try { + await storage.bucket(bucketName).setMetadata({ + iamConfiguration: { + publicAccessPrevention: 'enforced', + }, + }); + + console.log( + `Public access prevention is set to enforced for ${bucketName}.` + ); + } catch (error) { + console.error( + 'Error executing set public access prevention enforced:', + error.message || error + ); + } + } + + setPublicAccessPreventionEnforced(); + // [END storage_set_public_access_prevention_enforced] +} + +main(...process.argv.slice(2)); diff --git a/storage/setPublicAccessPreventionInherited.js b/storage/setPublicAccessPreventionInherited.js new file mode 100644 index 0000000000..c0fc042ad5 --- /dev/null +++ b/storage/setPublicAccessPreventionInherited.js @@ -0,0 +1,58 @@ +// Copyright 2021 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_set_public_access_prevention_inherited] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The name of your GCS bucket + // const bucketName = 'Name of a bucket, e.g. my-bucket'; + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + async function setPublicAccessPreventionInherited() { + // Sets public access prevention to 'inherited' for the bucket + try { + await storage.bucket(bucketName).setMetadata({ + iamConfiguration: { + publicAccessPrevention: 'inherited', + }, + }); + + console.log(`Public access prevention is 'inherited' for ${bucketName}.`); + } catch (error) { + console.error( + 'Error executing set public access prevention inherited:', + error.message || error + ); + } + } + + setPublicAccessPreventionInherited(); + // [END storage_set_public_access_prevention_inherited] +} +main(...process.argv.slice(2)); diff --git a/storage/setRPOAsyncTurbo.js b/storage/setRPOAsyncTurbo.js new file mode 100644 index 0000000000..cec5bf9187 --- /dev/null +++ b/storage/setRPOAsyncTurbo.js @@ -0,0 +1,60 @@ +// Copyright 2022 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_set_rpo_async_turbo] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The name of your GCS bucket in a dual-region + // const bucketName = 'Name of a bucket, e.g. my-bucket'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + // Enable turbo replication for the bucket by setting rpo to ASYNC_TURBO. + // The bucket must be a dual-region bucket. + async function setRPOAsyncTurbo() { + try { + await storage.bucket(bucketName).setMetadata({ + rpo: 'ASYNC_TURBO', + }); + + console.log(`Turbo replication enabled for ${bucketName}.`); + } catch (error) { + console.error( + 'Error executing set RPO async turbo:', + error.message || error + ); + } + } + + setRPOAsyncTurbo(); + // [END storage_set_rpo_async_turbo] +} + +main(...process.argv.slice(2)); diff --git a/storage/setRPODefault.js b/storage/setRPODefault.js new file mode 100644 index 0000000000..9d5daa48e6 --- /dev/null +++ b/storage/setRPODefault.js @@ -0,0 +1,57 @@ +// Copyright 2022 Google LLC +// +// 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 main(bucketName = 'my-bucket') { + // [START storage_set_rpo_default] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The name of your GCS bucket in a dual-region + // const bucketName = 'Name of a bucket, e.g. my-bucket'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + // Disable turbo replication for the bucket by setting RPO to default. + // The bucket must be a dual-region bucket. + async function setRPODefault() { + try { + await storage.bucket(bucketName).setMetadata({ + rpo: 'DEFAULT', + }); + + console.log(`Turbo replication disabled for ${bucketName}.`); + } catch (error) { + console.error('Error executing set RPO default:', error.message || error); + } + } + + setRPODefault(); + // [END storage_set_rpo_default] +} + +main(...process.argv.slice(2)); diff --git a/storage/setSoftDeletePolicy.js b/storage/setSoftDeletePolicy.js new file mode 100644 index 0000000000..30f7da9d06 --- /dev/null +++ b/storage/setSoftDeletePolicy.js @@ -0,0 +1,56 @@ +/** + * Copyright 2025 Google LLC + * + * 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'; + +function main(bucketName = 'my-bucket') { + // [START storage_set_soft_delete_policy] + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // The ID of your GCS bucket + // const bucketName = 'your-unique-bucket-name'; + + // Imports the Google Cloud client library + const {Storage} = require('@google-cloud/storage'); + + // Creates a client + const storage = new Storage(); + + async function setSoftDeletePolicy() { + try { + const options = { + softDeletePolicy: { + retentionDurationSeconds: 604800, // 7 days (in seconds) + }, + }; + + const [metadata] = await storage.bucket(bucketName).setMetadata(options); + + console.log(`Bucket ${metadata.name} soft delete policy set to 7 days`); + } catch (error) { + console.error( + 'Error executing set soft delete policy:', + error.message || error + ); + } + } + + setSoftDeletePolicy(); + // [END storage_set_soft_delete_policy] +} + +main(...process.argv.slice(2)); diff --git a/storage/system-test/buckets.test.js b/storage/system-test/buckets.test.js new file mode 100644 index 0000000000..4e2a03ebe9 --- /dev/null +++ b/storage/system-test/buckets.test.js @@ -0,0 +1,485 @@ +// Copyright 2019 Google LLC +// +// 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 {Storage} = require('@google-cloud/storage'); +const {assert} = require('chai'); +const {after, it} = require('mocha'); +const cp = require('child_process'); +const uuid = require('uuid'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const storage = new Storage(); +const samplesTestBucketPrefix = `nodejs-storage-samples-${uuid.v4()}`; +const bucketName = `${samplesTestBucketPrefix}-a`; +const bucketNameDualRegion = `${samplesTestBucketPrefix}-b`; +const bucketNameDualRegionTurbo = `${samplesTestBucketPrefix}-c`; +const bucketNameWithClassAndLocation = `${samplesTestBucketPrefix}-d`; +const bucketNameAutoclass = `${samplesTestBucketPrefix}-e`; +const bucketNameObjectRetention = `${samplesTestBucketPrefix}-f`; +const bucketNameHierarchicalNamespace = `${samplesTestBucketPrefix}-g`; +const defaultKmsKeyName = process.env.GOOGLE_CLOUD_KMS_KEY_ASIA; +const bucket = storage.bucket(bucketName); +const bucketWithClassAndLocation = storage.bucket( + bucketNameWithClassAndLocation +); +const dualRegionBucket = storage.bucket(bucketNameDualRegion); +const dualRegionBucketTurbo = storage.bucket(bucketNameDualRegionTurbo); +const objectRetentionBucket = storage.bucket(bucketNameObjectRetention); + +const PUBLIC_ACCESS_PREVENTION_INHERITED = 'inherited'; +const PUBLIC_ACCESS_PREVENTION_ENFORCED = 'enforced'; + +const DUAL_REGION = { + LOCATION: 'US', + REGIONS: ['US-EAST1', 'US-WEST1'], +}; +const RPO_ASYNC_TURBO = 'ASYNC_TURBO'; +const RPO_DEFAULT = 'DEFAULT'; + +async function deleteAllBucketsAsync() { + const [buckets] = await storage.getBuckets({prefix: samplesTestBucketPrefix}); + + for (const bucket of buckets) { + await bucket.deleteFiles({force: true}); + await bucket.delete({ignoreNotFound: true}); + } +} + +after(deleteAllBucketsAsync); +afterEach(async () => { + await new Promise(res => setTimeout(res, 1000)); +}); + +it('should create a bucket', async () => { + const output = execSync(`node createNewBucket.js ${bucketName}`); + assert.match(output, new RegExp(`Bucket ${bucketName} created`)); + const [exists] = await bucket.exists(); + assert.strictEqual(exists, true); +}); + +it('should list buckets', () => { + const output = execSync('node listBuckets.js'); + assert.match(output, /Buckets:/); + assert.match(output, new RegExp(bucketName)); +}); + +it('should get bucket metadata', async () => { + const output = execSync(`node bucketMetadata.js ${bucketName}`); + assert.include(output, bucketName); +}); + +it('should set autoclass terminal storage class to ARCHIVE', async () => { + await storage.createBucket(bucketNameAutoclass, { + autoclass: { + enabled: true, + terminalStorageClass: 'NEARLINE', + }, + }); + const output = execSync( + `node setAutoclass.js ${bucketNameAutoclass} ${true} ARCHIVE` + ); + assert.include(output, 'ARCHIVE'); +}); + +it('should disable autoclass', async () => { + const output = execSync( + `node setAutoclass.js ${bucketNameAutoclass} ${false}` + ); + assert.include(output, 'Autoclass'); +}); + +it('should get autoclass', async () => { + const output = execSync(`node getAutoclass.js ${bucketNameAutoclass}`); + assert.include(output, `Autoclass is disabled for ${bucketNameAutoclass}`); +}); + +it('should set a buckets default KMS key', async () => { + const output = execSync( + `node enableDefaultKMSKey.js ${bucketName} ${defaultKmsKeyName}` + ); + assert.include( + output, + `Default KMS key for ${bucketName} was set to ${defaultKmsKeyName}` + ); + const metadata = await bucket.getMetadata(); + assert.strictEqual( + metadata[0].encryption.defaultKmsKeyName, + defaultKmsKeyName + ); +}); + +it('should remove a buckets default KMS key', async () => { + const output = execSync(`node removeDefaultKMSKey.js ${bucketName}`); + assert.include(output, `Default KMS key was removed from ${bucketName}`); + const [metadata] = await bucket.getMetadata(); + assert.ok(!metadata.encryption); +}); + +it("should enable a bucket's uniform bucket-level access", async () => { + const output = execSync( + `node enableUniformBucketLevelAccess.js ${bucketName}` + ); + assert.match( + output, + new RegExp(`Uniform bucket-level access was enabled for ${bucketName}`) + ); + + const metadata = await bucket.getMetadata(); + assert.strictEqual( + metadata[0].iamConfiguration.uniformBucketLevelAccess.enabled, + true + ); +}); + +it("should get a bucket's uniform bucket-level access metadata", async () => { + const output = execSync(`node getUniformBucketLevelAccess.js ${bucketName}`); + + assert.match( + output, + new RegExp(`Uniform bucket-level access is enabled for ${bucketName}`) + ); + + const [metadata] = await bucket.getMetadata(); + assert.ok(metadata.iamConfiguration.uniformBucketLevelAccess.enabled); + assert.strictEqual( + metadata.iamConfiguration.uniformBucketLevelAccess.lockedTime !== null, + true + ); +}); + +it("should disable a bucket's uniform bucket-level access", async () => { + const output = execSync( + `node disableUniformBucketLevelAccess.js ${bucketName}` + ); + assert.match( + output, + new RegExp(`Uniform bucket-level access was disabled for ${bucketName}`) + ); + + const metadata = await bucket.getMetadata(); + assert.strictEqual( + metadata[0].iamConfiguration.uniformBucketLevelAccess.enabled, + false + ); +}); + +it('should configure a bucket cors', async () => { + execSync( + `node configureBucketCors.js ${bucketName} 3600 POST http://example.appspot.com content-type` + ); + await bucket.getMetadata(); + assert.deepStrictEqual(bucket.metadata.cors[0], { + origin: ['http://example.appspot.com'], + method: ['POST'], + responseHeader: ['content-type'], + maxAgeSeconds: 3600, + }); +}); + +it('should remove a bucket cors configuration', async () => { + const output = execSync(`node removeBucketCors.js ${bucketName}`); + assert.include( + output, + `Removed CORS configuration from bucket ${bucketName}` + ); + await bucket.getMetadata(); + assert.ok(!bucket.metadata.cors); +}); + +it('should set public access prevention to enforced', async () => { + const output = execSync( + `node setPublicAccessPreventionEnforced.js ${bucketName}` + ); + assert.match( + output, + new RegExp(`Public access prevention is set to enforced for ${bucketName}.`) + ); + + const metadata = await bucket.getMetadata(); + assert.strictEqual( + metadata[0].iamConfiguration.publicAccessPrevention, + PUBLIC_ACCESS_PREVENTION_ENFORCED + ); +}); + +it("should get a bucket's public access prevention metadata", async () => { + await storage.bucket(bucketName).setMetadata({ + iamConfiguration: { + publicAccessPrevention: PUBLIC_ACCESS_PREVENTION_ENFORCED, + }, + }); + + const output = execSync(`node getPublicAccessPrevention.js ${bucketName}`); + + assert.match( + output, + new RegExp(`Public access prevention is enforced for ${bucketName}.`) + ); + + const [metadata] = await bucket.getMetadata(); + assert.ok(metadata.iamConfiguration.publicAccessPrevention); +}); + +it('should set public access prevention to inherited', async () => { + const output = execSync( + `node setPublicAccessPreventionInherited.js ${bucketName}` + ); + assert.match( + output, + new RegExp(`Public access prevention is 'inherited' for ${bucketName}.`) + ); + + const metadata = await bucket.getMetadata(); + assert.strictEqual( + metadata[0].iamConfiguration.publicAccessPrevention, + PUBLIC_ACCESS_PREVENTION_INHERITED + ); +}); + +it('should create a dual-region bucket', async () => { + const output = execSync( + `node createBucketWithDualRegion.js ${bucketNameDualRegion} ${DUAL_REGION.LOCATION} ${DUAL_REGION.REGIONS[0]} ${DUAL_REGION.REGIONS[1]}` + ); + + // Ensure the sample outputs the desired result + assert.include(output, bucketNameDualRegion); + assert.include(output, DUAL_REGION.LOCATION); + assert.include(output, DUAL_REGION.REGIONS[0]); + assert.include(output, DUAL_REGION.REGIONS[1]); + assert.include(output, 'dual-region'); + + // Make API request for further verification + const [exists] = await dualRegionBucket.exists(); + assert.strictEqual(exists, true); + + const [metadata] = await dualRegionBucket.getMetadata(); + + assert.strictEqual(metadata.location, DUAL_REGION.LOCATION); + + assert(metadata.customPlacementConfig); + assert(Array.isArray(metadata.customPlacementConfig.dataLocations)); + + const dataLocations = metadata.customPlacementConfig.dataLocations; + + assert(dataLocations.includes(DUAL_REGION.REGIONS[0])); + assert(dataLocations.includes(DUAL_REGION.REGIONS[1])); + + assert.strictEqual(metadata.locationType, 'dual-region'); +}); + +it('should create a dual-region bucket with turbo replication enabled', async () => { + const output = execSync( + `node createBucketWithTurboReplication.js ${bucketNameDualRegionTurbo}` + ); + assert.match( + output, + new RegExp( + `${bucketNameDualRegionTurbo} created with the recovery point objective \\(RPO\\) set to ASYNC_TURBO in NAM4.` + ) + ); + const [exists] = await dualRegionBucketTurbo.exists(); + assert.strictEqual(exists, true); +}); + +it("should get a bucket's RPO metadata", async () => { + await storage.bucket(bucketNameDualRegionTurbo).setMetadata({ + rpo: RPO_ASYNC_TURBO, + }); + + const output = execSync(`node getRPO.js ${bucketNameDualRegionTurbo}`); + assert.match( + output, + new RegExp(`RPO is ASYNC_TURBO for ${bucketNameDualRegionTurbo}.`) + ); + + const metadata = await dualRegionBucketTurbo.getMetadata(); + assert.strictEqual(metadata[0].rpo, RPO_ASYNC_TURBO); +}); + +it("should set a bucket's RPO to ASYNC_TURBO", async () => { + const output = execSync( + `node setRPOAsyncTurbo.js ${bucketNameDualRegionTurbo}` + ); + assert.match( + output, + new RegExp(`Turbo replication enabled for ${bucketNameDualRegionTurbo}.`) + ); + + const metadata = await dualRegionBucketTurbo.getMetadata(); + assert.strictEqual(metadata[0].rpo, RPO_ASYNC_TURBO); +}); + +it("should set a bucket's RPO to DEFAULT", async () => { + const output = execSync(`node setRPODefault.js ${bucketNameDualRegionTurbo}`); + assert.match( + output, + new RegExp(`Turbo replication disabled for ${bucketNameDualRegionTurbo}.`) + ); + + const metadata = await dualRegionBucketTurbo.getMetadata(); + assert.strictEqual(metadata[0].rpo, RPO_DEFAULT); +}); + +it('should create a hierarchical namespace enabled bucket', async () => { + const output = execSync( + `node createBucketWithHierarchicalNamespace.js ${bucketNameHierarchicalNamespace}` + ); + assert.match( + output, + new RegExp( + `Created '${bucketNameHierarchicalNamespace}' with hierarchical namespace enabled.` + ) + ); + + const metadata = await dualRegionBucketTurbo.getMetadata(); + assert.strictEqual(metadata[0].rpo, RPO_DEFAULT); +}); + +it("should add a bucket's website configuration", async () => { + const output = execSync( + `node addBucketWebsiteConfiguration.js ${bucketName} http://example.com http://example.com/404.html` + ); + + assert.include( + output, + `Static website bucket ${bucketName} is set up to use http://example.com as the index page and http://example.com/404.html as the 404 page` + ); + + const [metadata] = await bucket.getMetadata(); + assert.deepStrictEqual(metadata.website, { + mainPageSuffix: 'http://example.com', + notFoundPage: 'http://example.com/404.html', + }); +}); + +/** + * TODO: Re-enable once the test environment allows public IAM roles. + * Currently disabled to avoid 403 errors when adding 'allUsers' or + * 'allAuthenticatedUsers' permissions. + */ +it.skip('should make bucket publicly readable', async () => { + const output = execSync(`node makeBucketPublic.js ${bucketName}`); + assert.match( + output, + new RegExp(`Bucket ${bucketName} is now publicly readable`) + ); + const [policy] = await bucket.iam.getPolicy(); + const objectViewerBinding = policy.bindings.filter(binding => { + return binding.role === 'roles/storage.legacyBucketReader'; + })[0]; + + assert(objectViewerBinding.members.includes('allUsers')); +}); + +it("should enable a bucket's versioning", async () => { + const output = execSync(`node enableBucketVersioning.js ${bucketName}`); + assert.include(output, `Versioning is enabled for bucket ${bucketName}`); + await bucket.getMetadata(); + assert.strictEqual(bucket.metadata.versioning.enabled, true); +}); + +it("should disable a bucket's versioning", async () => { + const output = execSync(`node disableBucketVersioning.js ${bucketName}`); + assert.include(output, `Versioning is disabled for bucket ${bucketName}`); + await bucket.getMetadata(); + assert.strictEqual(bucket.metadata.versioning.enabled, false); +}); + +it('should add label to bucket', async () => { + const output = execSync( + `node addBucketLabel.js ${bucketName} labelone labelonevalue` + ); + assert.include(output, `Added label to bucket ${bucketName}`); + const [labels] = await storage.bucket(bucketName).getLabels(); + assert.isTrue('labelone' in labels); +}); + +it('should remove label to bucket', async () => { + const output = execSync(`node removeBucketLabel.js ${bucketName} labelone`); + assert.include(output, `Removed labels from bucket ${bucketName}`); + const [labels] = await storage.bucket(bucketName).getLabels(); + assert.isFalse('labelone' in labels); +}); + +it("should change a bucket's default storage class", async () => { + const output = execSync( + `node changeDefaultStorageClass.js ${bucketName} coldline` + ); + assert.include(output, `${bucketName} has been set to coldline`); + const [metadata] = await bucket.getMetadata(); + assert.strictEqual(metadata.storageClass, 'COLDLINE'); +}); + +it('should create bucket with storage class and location', async () => { + const output = execSync( + `node createBucketWithStorageClassAndLocation.js ${bucketNameWithClassAndLocation} coldline ASIA` + ); + assert.include( + output, + `${bucketNameWithClassAndLocation} created with coldline class in ASIA` + ); + const [metadata] = await bucketWithClassAndLocation.getMetadata(); + assert.strictEqual(metadata.storageClass, 'COLDLINE'); + assert.strictEqual(metadata.location, 'ASIA'); +}); + +it("should set a bucket's soft delete policy", async () => { + const output = execSync(`node setSoftDeletePolicy.js ${bucketName}`); + assert.include( + output, + `Bucket ${bucketName} soft delete policy set to 7 days` + ); +}); + +it("should get a bucket's soft delete policy", async () => { + const output = execSync(`node getSoftDeletePolicy.js ${bucketName}`); + assert.include(output, `Soft delete policy for ${bucketName}`); + assert.include(output, 'Soft delete Period: 604800 seconds'); + assert.match(output, new RegExp('Effective Time:')); +}); + +it("should disable a bucket's soft delete policy", async () => { + const output = execSync(`node disableSoftDelete.js ${bucketName}`); + assert.include( + output, + `Bucket ${bucketName} soft delete policy was disabled` + ); + await bucket.getMetadata(); + assert.strictEqual( + bucket.metadata.softDeletePolicy.retentionDurationSeconds, + '0' + ); +}); + +it('should delete a bucket', async () => { + const output = execSync(`node deleteBucket.js ${bucketName}`); + assert.match(output, new RegExp(`Bucket ${bucketName} deleted`)); + const [exists] = await bucket.exists(); + assert.strictEqual(exists, false); +}); + +it('should create a bucket with object retention enabled', async () => { + const output = execSync( + `node createBucketWithObjectRetention.js ${bucketNameObjectRetention}` + ); + assert.include( + output, + `Created '${bucketNameObjectRetention}' with object retention enabled setting: Enabled` + ); + const [metadata] = await objectRetentionBucket.getMetadata(); + assert.strictEqual(metadata.objectRetention.mode, 'Enabled'); +}); diff --git a/storage/system-test/test_9d800329-00da-4cdd-9a3e-7ac6743d5813.txt b/storage/system-test/test_9d800329-00da-4cdd-9a3e-7ac6743d5813.txt new file mode 100644 index 0000000000..e69de29bb2 From aea8df54309dd7cdf8b76051ef75e35f5f98b876 Mon Sep 17 00:00:00 2001 From: Angel Caamal Date: Mon, 23 Mar 2026 15:45:58 +0000 Subject: [PATCH 2/2] test(storage): improve system test cases --- storage/system-test/buckets.test.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/storage/system-test/buckets.test.js b/storage/system-test/buckets.test.js index 4e2a03ebe9..00742215d4 100644 --- a/storage/system-test/buckets.test.js +++ b/storage/system-test/buckets.test.js @@ -345,8 +345,14 @@ it('should create a hierarchical namespace enabled bucket', async () => { ) ); - const metadata = await dualRegionBucketTurbo.getMetadata(); - assert.strictEqual(metadata[0].rpo, RPO_DEFAULT); + const [metadata] = await storage + .bucket(bucketNameHierarchicalNamespace) + .getMetadata(); + assert.deepStrictEqual(metadata.hierarchicalNamespace, {enabled: true}); + assert.strictEqual( + metadata.iamConfiguration.uniformBucketLevelAccess.enabled, + true + ); }); it("should add a bucket's website configuration", async () => {