diff --git a/storage-control/createAnywhereCache.js b/storage-control/createAnywhereCache.js new file mode 100644 index 0000000000..1b43d6e4d5 --- /dev/null +++ b/storage-control/createAnywhereCache.js @@ -0,0 +1,122 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName, zoneName) { + // [START storage_control_create_anywhere_cache] + + /** + * Creates an Anywhere Cache instance for a Cloud Storage bucket. + * Anywhere Cache is a feature that provides an SSD-backed zonal read cache. + * This can significantly improve read performance for frequently accessed data + * by caching it in the same zone as your compute resources. + * + * @param {string} bucketName The name of the bucket to create the cache for. + * Example: 'your-gcp-bucket-name' + * @param {string} zoneName The zone where the cache will be created. + * Example: 'us-central1-a' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callCreateAnywhereCache() { + const bucketPath = controlClient.bucketPath('_', bucketName); + + // Create the request + const request = { + parent: bucketPath, + anywhereCache: { + zone: zoneName, + ttl: { + seconds: '10000s', + }, // Optional. Default: '86400s'(1 day) + admissionPolicy: 'admit-on-first-miss', // Optional. Default: 'admit-on-first-miss' + }, + }; + + try { + // Run the request, which returns an Operation object + const [operation] = await controlClient.createAnywhereCache(request); + console.log(`Waiting for operation ${operation.name} to complete...`); + + // Wait for the operation to complete and get the final resource + const anywhereCache = await checkCreateAnywhereCacheProgress( + operation.name + ); + console.log(`Created anywhere cache: ${anywhereCache.result.name}.`); + } catch (error) { + // Handle any error that occurred during the creation or polling process. + console.error('Failed to create Anywhere Cache:', error.message); + throw error; + } + } + + // A custom function to check the operation's progress. + async function checkCreateAnywhereCacheProgress(operationName) { + let operation = {done: false}; + console.log('Starting manual polling for operation...'); + + // Poll the operation until it's done. + while (!operation.done) { + await new Promise(resolve => setTimeout(resolve, 180000)); // Wait for 3 minutes before the next check. + const request = { + name: operationName, + }; + try { + const [latestOperation] = await controlClient.getOperation(request); + operation = latestOperation; + } catch (err) { + // Handle potential errors during polling. + console.error('Error while polling:', err.message); + break; // Exit the loop on error. + } + } + + // Return the final result of the operation. + if (operation.response) { + // Decode the operation response into a usable Operation object + const decodeOperation = new controlClient._gaxModule.Operation( + operation, + controlClient.descriptors.longrunning.createAnywhereCache, + controlClient._gaxModule.createDefaultBackoffSettings() + ); + // Return the decoded operation + return decodeOperation; + } else { + // If there's no response, it indicates an issue, so throw an error + throw new Error('Operation completed without a response.'); + } + } + + callCreateAnywhereCache(); + // [END storage_control_create_anywhere_cache] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/storage-control/disableAnywhereCache.js b/storage-control/disableAnywhereCache.js new file mode 100644 index 0000000000..f4487d725f --- /dev/null +++ b/storage-control/disableAnywhereCache.js @@ -0,0 +1,104 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName, cacheName) { + // [START storage_control_disable_anywhere_cache] + /** + * Disables an Anywhere Cache instance. + * + * Disabling a cache is the first step to permanently removing it. Once disabled, + * the cache stops ingesting new data. After a grace period, the cache and its + * contents are deleted. This is useful for decommissioning caches that are no + * longer needed. + * + * @param {string} bucketName The name of the bucket where the cache resides. + * Example: 'your-gcp-bucket-name' + * @param {string} cacheName The unique identifier of the cache instance to disable. + * Example: 'cacheName' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callDisableAnywhereCache() { + // You have a one-hour grace period after disabling a cache to resume it and prevent its deletion. + // If you don't resume the cache within that hour, it will be deleted, its data will be evicted, + // and the cache will be permanently removed from the bucket. + + const anywhereCachePath = controlClient.anywhereCachePath( + '_', + bucketName, + cacheName + ); + + // Create the request + const request = { + name: anywhereCachePath, + }; + + try { + // Run request. This initiates the disablement process. + const [response] = await controlClient.disableAnywhereCache(request); + + console.log( + `Successfully initiated disablement for Anywhere Cache: '${cacheName}'.` + ); + console.log(` Current State: ${response.state}`); + console.log(` Resource Name: ${response.name}`); + } catch (error) { + // Catch and handle potential API errors. + console.error( + `Error disabling Anywhere Cache '${cacheName}': ${error.message}` + ); + + if (error.code === 5) { + // NOT_FOUND (gRPC code 5) error can occur if the bucket or cache does not exist. + console.error( + `Please ensure the cache '${cacheName}' exists in bucket '${bucketName}'.` + ); + } else if (error.code === 9) { + // FAILED_PRECONDITION (gRPC code 9) can occur if the cache is already being disabled + // or is not in a RUNNING state that allows the disable operation. + console.error( + `Cache '${cacheName}' may not be in a state that allows disabling (e.g., must be RUNNING).` + ); + } + throw error; + } + // Run request + const [response] = await controlClient.disableAnywhereCache(request); + console.log(`Disabled anywhere cache: ${response.name}.`); + } + + callDisableAnywhereCache(); + // [END storage_control_disable_anywhere_cache] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/storage-control/getAnywhereCache.js b/storage-control/getAnywhereCache.js new file mode 100644 index 0000000000..2633ede7e4 --- /dev/null +++ b/storage-control/getAnywhereCache.js @@ -0,0 +1,91 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName, cacheName) { + // [START storage_control_get_anywhere_cache] + /** + * Retrieves details of a specific Anywhere Cache instance. + * + * This function is useful for checking the current state, configuration (like TTL), + * and other metadata of an existing cache. + * + * @param {string} bucketName The name of the bucket where the cache resides. + * Example: 'your-gcp-bucket-name' + * @param {string} cacheName The unique identifier of the cache instance. + * Example: 'my-anywhere-cache-id' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callGetAnywhereCache() { + const anywhereCachePath = controlClient.anywhereCachePath( + '_', + bucketName, + cacheName + ); + + // Create the request + const request = { + name: anywhereCachePath, + }; + + try { + // Run request + const [response] = await controlClient.getAnywhereCache(request); + console.log(`Anywhere Cache details for '${cacheName}':`); + console.log(` Name: ${response.name}`); + console.log(` Zone: ${response.zone}`); + console.log(` State: ${response.state}`); + console.log(` TTL: ${response.ttl.seconds}s`); + console.log(` Admission Policy: ${response.admissionPolicy}`); + console.log( + ` Create Time: ${new Date(response.createTime.seconds * 1000).toISOString()}` + ); + } catch (error) { + // Handle errors (e.g., cache not found, permission denied). + console.error( + `Error retrieving Anywhere Cache '${cacheName}': ${error.message}` + ); + + if (error.code === 5) { + console.error( + `Ensure the cache '${cacheName}' exists in bucket '${bucketName}'.` + ); + } + throw error; + } + } + + callGetAnywhereCache(); + // [END storage_control_get_anywhere_cache] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/storage-control/listAnywhereCaches.js b/storage-control/listAnywhereCaches.js new file mode 100644 index 0000000000..9bf5175981 --- /dev/null +++ b/storage-control/listAnywhereCaches.js @@ -0,0 +1,82 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName) { + // [START storage_control_list_anywhere_caches] + /** + * Lists all Anywhere Cache instances for a Cloud Storage bucket. + * This function helps you discover all active and pending caches associated with + * a specific bucket, which is useful for auditing and management. + * + * @param {string} bucketName The name of the bucket to list caches for. + * Example: 'your-gcp-bucket-name' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callListAnywhereCaches() { + const bucketPath = controlClient.bucketPath('_', bucketName); + + // Create the request + const request = { + parent: bucketPath, + }; + + try { + // Run request. The response is an array where the first element is the list of caches. + const [response] = await controlClient.listAnywhereCaches(request); + + if (response && response.length > 0) { + console.log( + `Found ${response.length} Anywhere Caches for bucket: ${bucketName}` + ); + for (const anywhereCache of response) { + console.log(anywhereCache.name); + } + } else { + // Case: Successful but empty list (No Anywhere Caches found) + console.log(`No Anywhere Caches found for bucket: ${bucketName}.`); + } + } catch (error) { + console.error( + `Error listing Anywhere Caches for bucket ${bucketName}:`, + error.message + ); + throw error; + } + } + + callListAnywhereCaches(); + // [END storage_control_list_anywhere_caches] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/storage-control/package.json b/storage-control/package.json index 0f6d932845..98f61559c5 100644 --- a/storage-control/package.json +++ b/storage-control/package.json @@ -12,8 +12,8 @@ "author": "Google Inc.", "license": "Apache-2.0", "devDependencies": { - "@google-cloud/storage": "^7.12.0", - "@google-cloud/storage-control": "^0.2.0", + "@google-cloud/storage": "^7.17.0", + "@google-cloud/storage-control": "^0.5.0", "c8": "^10.0.0", "chai": "^4.5.0", "mocha": "^10.7.0", diff --git a/storage-control/pauseAnywhereCache.js b/storage-control/pauseAnywhereCache.js new file mode 100644 index 0000000000..dcb974b0fe --- /dev/null +++ b/storage-control/pauseAnywhereCache.js @@ -0,0 +1,92 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName, cacheName) { + // [START storage_control_pause_anywhere_cache] + /** + * Pauses an Anywhere Cache instance. + * + * This synchronous function stops the ingestion of new data for a cache that's in a RUNNING state. + * While PAUSED, you can still read existing data (which resets the TTL), but no new data is ingested. + * The cache can be returned to the RUNNING state by calling the resume function. + * + * @param {string} bucketName The name of the bucket where the cache resides. + * Example: 'your-gcp-bucket-name' + * @param {string} cacheName The unique identifier of the cache instance. + * Example: 'my-anywhere-cache-id' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callPauseAnywhereCache() { + const anywhereCachePath = controlClient.anywhereCachePath( + '_', + bucketName, + cacheName + ); + + // Create the request + const request = { + name: anywhereCachePath, + }; + + try { + // Run request + const [response] = await controlClient.pauseAnywhereCache(request); + + console.log(`Successfully paused anywhere cache: ${response.name}.`); + console.log(` Current State: ${response.state}`); + } catch (error) { + // Catch and handle potential API errors. + console.error( + `Error pausing Anywhere Cache '${cacheName}': ${error.message}` + ); + + if (error.code === 5) { + // NOT_FOUND (gRPC code 5) + console.error( + `Please ensure the cache '${cacheName}' exists in bucket '${bucketName}'.` + ); + } else if (error.code === 9) { + // FAILED_PRECONDITION (gRPC code 9) + console.error( + `Cache '${cacheName}' may not be in a state that allows pausing (e.g., must be RUNNING).` + ); + } + throw error; + } + } + + callPauseAnywhereCache(); + // [END storage_control_pause_anywhere_cache] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/storage-control/resumeAnywhereCache.js b/storage-control/resumeAnywhereCache.js new file mode 100644 index 0000000000..1cea5035d3 --- /dev/null +++ b/storage-control/resumeAnywhereCache.js @@ -0,0 +1,91 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName, cacheName) { + // [START storage_control_resume_anywhere_cache] + /** + * Resumes a disabled Anywhere Cache instance. + * + * This action reverts a cache from a PAUSED state or a DISABLED state back to RUNNING, + * provided it is done within the 1-hour grace period before the cache is permanently deleted. + * + * @param {string} bucketName The name of the bucket where the cache resides. + * Example: 'your-gcp-bucket-name' + * @param {string} cacheName The unique identifier of the cache instance. + * Example: 'my-anywhere-cache-id' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callResumeAnywhereCache() { + const anywhereCachePath = controlClient.anywhereCachePath( + '_', + bucketName, + cacheName + ); + + // Create the request + const request = { + name: anywhereCachePath, + }; + + try { + // Run request + const [response] = await controlClient.resumeAnywhereCache(request); + + console.log(`Successfully resumed anywhere cache: ${response.name}.`); + console.log(` Current State: ${response.state}`); + } catch (error) { + // Catch and handle potential API errors. + console.error( + `Error resuming Anywhere Cache '${cacheName}': ${error.message}` + ); + + if (error.code === 5) { + // NOT_FOUND (gRPC code 5) + console.error( + `Please ensure the cache '${cacheName}' exists in bucket '${bucketName}'.` + ); + } else if (error.code === 9) { + // FAILED_PRECONDITION (gRPC code 9) + console.error( + `Cache '${cacheName}' may not be in a state that allows resuming (e.g., already RUNNING or past the 1-hour deletion grace period).` + ); + } + throw error; + } + } + + callResumeAnywhereCache(); + // [END storage_control_resume_anywhere_cache] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/storage-control/system-test/anywhereCache.test.js b/storage-control/system-test/anywhereCache.test.js new file mode 100644 index 0000000000..59a6bbadb6 --- /dev/null +++ b/storage-control/system-test/anywhereCache.test.js @@ -0,0 +1,164 @@ +// 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 +// +// https://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. + +const {Storage, Bucket} = require('@google-cloud/storage'); +const {StorageControlClient} = require('@google-cloud/storage-control').v2; +const cp = require('child_process'); +const {assert} = require('chai'); +const {describe, it, before, after} = require('mocha'); +const uuid = require('uuid'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const bucketPrefix = `storage-control-samples-${uuid.v4()}`; +const bucketName = `${bucketPrefix}-a`; +const controlClient = new StorageControlClient(); +const storage = new Storage(); +const bucket = new Bucket(storage, bucketName); +const zoneName = 'us-west1-c'; +const cacheName = 'us-west1-c'; +let anywhereCachePath; + +// Skipped to prevent CI timeouts caused by long-running operations. +// Un-skip for deliberate, manual runs. +describe.skip('Anywhere Cache', () => { + before(async () => { + await storage.createBucket(bucketName, { + iamConfiguration: { + uniformBucketLevelAccess: { + enabled: true, + }, + }, + hierarchicalNamespace: {enabled: true}, + location: 'us-west1', + }); + + anywhereCachePath = controlClient.anywhereCachePath( + '_', + bucketName, + cacheName + ); + }); + + after(async function () { + // Sets the timeout for the test to 3600000 milliseconds (1 hour). + // This is necessary for long-running operations, such as waiting for a + // cache to be disabled, to prevent the test from failing due to a timeout. + this.timeout(3600000); + let caches = false; + // The `while` loop will continue to run as long as the `caches` flag is `false`. + while (!caches) { + await new Promise(resolve => setTimeout(resolve, 30000)); + const bucketPath = controlClient.bucketPath('_', bucketName); + + try { + // Call the `listAnywhereCaches` method to check for any active caches. + // The response is an array of caches. + const [response] = await controlClient.listAnywhereCaches({ + parent: bucketPath, + }); + // Check if the response array is empty. If so, it means there are no more caches, and we can exit the loop. + if (response.length === 0) { + // Set `caches` to `true` to break out of the `while` loop. + caches = true; + } + } catch (err) { + console.error('Error while polling:', err.message); + break; + } + } + // After the loop has finished (i.e., no more caches are found), we proceed with deleting the bucket. + await bucket.delete(); + }); + + it('should create an anywhere cache', async function () { + // Sets the timeout for the test to 3600000 milliseconds (1 hour). + // This is necessary for long-running operations, such as waiting for a + // cache to be created, to prevent the test from failing due to a timeout. + this.timeout(3600000); + const output = execSync( + `node createAnywhereCache.js ${bucketName} ${zoneName}` + ); + assert.match(output, /Created anywhere cache:/); + assert.match(output, new RegExp(anywhereCachePath)); + }); + + it('should get an anywhere cache', async () => { + const output = execSync( + `node getAnywhereCache.js ${bucketName} ${cacheName}` + ); + const detailsHeader = `Anywhere Cache details for '${cacheName}':`; + assert.match(output, new RegExp(detailsHeader)); + assert.match(output, /Name:/); + assert.match(output, new RegExp(anywhereCachePath)); + assert.match(output, /Zone:/); + assert.match(output, /State:/); + assert.match(output, /TTL:/); + assert.match(output, /Admission Policy:/); + assert.match(output, /Create Time:/); + }); + + it('should list anywhere caches', async () => { + const output = execSync(`node listAnywhereCaches.js ${bucketName}`); + assert.match(output, new RegExp(anywhereCachePath)); + }); + + it('should update an anywhere cache', async () => { + const admissionPolicy = 'admit-on-second-miss'; + const output = execSync( + `node updateAnywhereCache.js ${bucketName} ${cacheName} ${admissionPolicy}` + ); + assert.match(output, /Updated anywhere cache:/); + assert.match(output, new RegExp(anywhereCachePath)); + }); + + it('should pause an anywhere cache', async () => { + const output = execSync( + `node pauseAnywhereCache.js ${bucketName} ${cacheName}` + ); + assert.match(output, /Successfully paused anywhere cache:/); + assert.match(output, new RegExp(anywhereCachePath)); + assert.match(output, /Current State:/); + }); + + it('should resume an anywhere cache', async () => { + const output = execSync( + `node resumeAnywhereCache.js ${bucketName} ${cacheName}` + ); + assert.match(output, /Successfully resumed anywhere cache:/); + assert.match(output, new RegExp(anywhereCachePath)); + assert.match(output, /Current State:/); + }); + + it('should disable an anywhere cache', async () => { + try { + const output = execSync( + `node disableAnywhereCache.js ${bucketName} ${cacheName}` + ); + assert.match( + output, + /Successfully initiated disablement for Anywhere Cache:/ + ); + assert.match(output, new RegExp(anywhereCachePath)); + assert.match(output, /Current State:/); + assert.match(output, /Resource Name:/); + } catch (error) { + const errorMessage = error.stderr.toString(); + + assert.match( + errorMessage, + /9 FAILED_PRECONDITION: The requested DISABLE operation can't be applied on cache in DISABLED state./ + ); + } + }); +}); diff --git a/storage-control/updateAnywhereCache.js b/storage-control/updateAnywhereCache.js new file mode 100644 index 0000000000..1d006e4119 --- /dev/null +++ b/storage-control/updateAnywhereCache.js @@ -0,0 +1,100 @@ +// 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 +// +// https://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 an Anywhere Cache + * instance with the Google Cloud Storage API. + * + * For more information, see the documentation at https://cloud.google.com/storage/docs/anywhere-cache. + */ + +function main(bucketName, cacheName, admissionPolicy) { + // [START storage_control_update_anywhere_cache] + /** + * Updates the Admission Policy of an Anywhere Cache instance. + * + * @param {string} bucketName The name of the bucket where the cache resides. + * Example: 'your-gcp-bucket-name' + * @param {string} cacheName The unique identifier of the cache instance to update. + * Example: 'my-anywhere-cache-id' + * @param {string} admissionPolicy Determines when data is ingested into the cache + * Example: 'admit-on-second-miss' + */ + + // Imports the Control library + const {StorageControlClient} = require('@google-cloud/storage-control').v2; + + // Instantiates a client + const controlClient = new StorageControlClient(); + + async function callUpdateAnywhereCache() { + const anywhereCachePath = controlClient.anywhereCachePath( + '_', + bucketName, + cacheName + ); + + // Create the request + const request = { + anywhereCache: { + name: anywhereCachePath, + admissionPolicy: admissionPolicy, + }, + updateMask: { + paths: ['admission_policy'], + }, + }; + + try { + // Run request + const [operation] = await controlClient.updateAnywhereCache(request); + console.log( + `Waiting for update operation ${operation.name} to complete...` + ); + + const [response] = await operation.promise(); + + console.log(`Updated anywhere cache: ${response.name}.`); + } catch (error) { + // Handle errors during the initial request or during the LRO polling. + console.error( + `Error updating Anywhere Cache '${cacheName}': ${error.message}` + ); + + if (error.code === 5) { + // NOT_FOUND (gRPC code 5) + console.error( + `Ensure the cache '${cacheName}' exists in bucket '${bucketName}'.` + ); + } else if (error.code === 3) { + // INVALID_ARGUMENT (gRPC code 3) + console.error( + `Ensure '${admissionPolicy}' is a valid Admission Policy.` + ); + } + throw error; + } + } + + callUpdateAnywhereCache(); + // [END storage_control_update_anywhere_cache] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2));