diff --git a/CODEOWNERS b/CODEOWNERS index 71b1e58997..8cefcf8e9c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -20,6 +20,7 @@ compute @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-revie iam @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers kms @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers orgpolicy @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers +tpu @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers recaptcha_enterprise @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers recaptcha_enterprise/demosite @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/recaptcha-customer-obsession-reviewers @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers secret-manager @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers @GoogleCloudPlatform/cloud-secrets-team diff --git a/tpu/queuedResources/createQueuedResourceNetwork.js b/tpu/queuedResources/createQueuedResourceNetwork.js new file mode 100644 index 0000000000..150392c743 --- /dev/null +++ b/tpu/queuedResources/createQueuedResourceNetwork.js @@ -0,0 +1,123 @@ +/* + * 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 + * + * 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'; + +async function main(tpuClient) { + // [START tpu_queued_resources_network] + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + const {Node, NetworkConfig, QueuedResource} = + require('@google-cloud/tpu').protos.google.cloud.tpu.v2alpha1; + + // Instantiate a tpuClient + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // Project ID or project number of the Google Cloud project, where you want to create queued resource. + const projectId = await tpuClient.getProjectId(); + + // The name of the network you want the node to connect to. The network should be assigned to your project. + const networkName = 'compute-tpu-network'; + + // The region of the network, that you want the node to connect to. + const region = 'us-central1'; + + // The name for your queued resource. + const queuedResourceName = 'queued-resource-1'; + + // The name for your node. + const nodeName = 'node-name-1'; + + // The zone in which to create the node. + // For more information about supported TPU types for specific zones, + // see https://cloud.google.com/tpu/docs/regions-zones + const zone = `${region}-a`; + + // The accelerator type that specifies the version and size of the node you want to create. + // For more information about supported accelerator types for each TPU version, + // see https://cloud.google.com/tpu/docs/system-architecture-tpu-vm#versions. + const tpuType = 'v2-8'; + + // Software version that specifies the version of the node runtime to install. For more information, + // see https://cloud.google.com/tpu/docs/runtimes + const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + + async function callCreateQueuedResourceNetwork() { + // Specify the network and subnetwork that you want to connect your TPU to. + const networkConfig = new NetworkConfig({ + enableExternalIps: true, + network: `projects/${projectId}/global/networks/${networkName}`, + subnetwork: `projects/${projectId}/regions/${region}/subnetworks/${networkName}`, + }); + + // Create a node + const node = new Node({ + name: nodeName, + zone, + acceleratorType: tpuType, + runtimeVersion: tpuSoftwareVersion, + networkConfig, + queuedResource: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + }); + + // Define parent for requests + const parent = `projects/${projectId}/locations/${zone}`; + + // Create queued resource + const queuedResource = new QueuedResource({ + name: queuedResourceName, + tpu: { + nodeSpec: [ + { + parent, + node, + nodeId: nodeName, + }, + ], + }, + }); + + const request = { + parent: `projects/${projectId}/locations/${zone}`, + queuedResource, + queuedResourceId: queuedResourceName, + }; + + const [operation] = await tpuClient.createQueuedResource(request); + + // Wait for the create operation to complete. + const [response] = await operation.promise(); + + // You can wait until TPU Node is READY, + // and check its status using getTpuVm() from `tpu_vm_get` sample. + return response; + } + return await callCreateQueuedResourceNetwork(); + // [END tpu_queued_resources_network] +} + +module.exports = main; + +// TODO(developer): Uncomment below lines before running the sample. +// main(...process.argv.slice(2)).catch(err => { +// console.error(err); +// process.exitCode = 1; +// }); diff --git a/tpu/queuedResources/createQueuedResourceStartupScript.js b/tpu/queuedResources/createQueuedResourceStartupScript.js new file mode 100644 index 0000000000..51c55225fa --- /dev/null +++ b/tpu/queuedResources/createQueuedResourceStartupScript.js @@ -0,0 +1,127 @@ +/* + * 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 + * + * 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'; + +async function main(tpuClient) { + // [START tpu_queued_resources_startup_script] + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + const {Node, NetworkConfig, QueuedResource} = + require('@google-cloud/tpu').protos.google.cloud.tpu.v2alpha1; + + // Instantiate a tpuClient + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // Project ID or project number of the Google Cloud project, where you want to create queued resource. + const projectId = await tpuClient.getProjectId(); + + // The name of the network you want the node to connect to. The network should be assigned to your project. + const networkName = 'compute-tpu-network'; + + // The region of the network, that you want the node to connect to. + const region = 'us-central1'; + + // The name for your queued resource. + const queuedResourceName = 'queued-resource-1'; + + // The name for your node. + const nodeName = 'node-name-1'; + + // The zone in which to create the node. + // For more information about supported TPU types for specific zones, + // see https://cloud.google.com/tpu/docs/regions-zones + const zone = `${region}-a`; + + // The accelerator type that specifies the version and size of the node you want to create. + // For more information about supported accelerator types for each TPU version, + // see https://cloud.google.com/tpu/docs/system-architecture-tpu-vm#versions. + const tpuType = 'v2-8'; + + // Software version that specifies the version of the node runtime to install. For more information, + // see https://cloud.google.com/tpu/docs/runtimes + const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + + async function callCreateQueuedResourceStartupScript() { + // Create a node + const node = new Node({ + name: nodeName, + zone, + acceleratorType: tpuType, + runtimeVersion: tpuSoftwareVersion, + // Define network + networkConfig: new NetworkConfig({ + enableExternalIps: true, + network: `projects/${projectId}/global/networks/${networkName}`, + subnetwork: `projects/${projectId}/regions/${region}/subnetworks/${networkName}`, + }), + queuedResource: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + metadata: { + // The script updates numpy to the latest version and logs the output to a file. + 'startup-script': `#!/bin/bash + echo "Hello World" > /var/log/hello.log + sudo pip3 install --upgrade numpy >> /var/log/hello.log 2>&1`, + }, + }); + + // Define parent for requests + const parent = `projects/${projectId}/locations/${zone}`; + + // Create queued resource + const queuedResource = new QueuedResource({ + name: queuedResourceName, + tpu: { + nodeSpec: [ + { + parent, + node, + nodeId: nodeName, + }, + ], + }, + }); + + const request = { + parent: `projects/${projectId}/locations/${zone}`, + queuedResource, + queuedResourceId: queuedResourceName, + }; + + const [operation] = await tpuClient.createQueuedResource(request); + + // Wait for the create operation to complete. + const [response] = await operation.promise(); + + // You can wait until TPU Node is READY, + // and check its status using getTpuVm() from `tpu_vm_get` sample. + return response; + } + return await callCreateQueuedResourceStartupScript(); + // [END tpu_queued_resources_startup_script] +} + +module.exports = main; + +// TODO(developer): Uncomment below lines before running the sample. +// main(...process.argv.slice(2)).catch(err => { +// console.error(err); +// process.exitCode = 1; +// }); diff --git a/tpu/queuedResources/createQueuedResourceTimeBound.js b/tpu/queuedResources/createQueuedResourceTimeBound.js new file mode 100644 index 0000000000..ce2c9a276b --- /dev/null +++ b/tpu/queuedResources/createQueuedResourceTimeBound.js @@ -0,0 +1,154 @@ +/* + * 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 + * + * 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'; + +async function main(tpuClient) { + // [START tpu_queued_resources_time_bound] + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + const {Node, NetworkConfig, QueuedResource} = + require('@google-cloud/tpu').protos.google.cloud.tpu.v2alpha1; + + // Instantiate a tpuClient + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // Project ID or project number of the Google Cloud project, where you want to create queued resource. + const projectId = await tpuClient.getProjectId(); + + // The name of the network you want the node to connect to. The network should be assigned to your project. + const networkName = 'compute-tpu-network'; + + // The region of the network, that you want the node to connect to. + const region = 'us-central1'; + + // The name for your queued resource. + const queuedResourceName = 'queued-resource-1'; + + // The name for your node. + const nodeName = 'node-name-1'; + + // The zone in which to create the node. + // For more information about supported TPU types for specific zones, + // see https://cloud.google.com/tpu/docs/regions-zones + const zone = `${region}-a`; + + // The accelerator type that specifies the version and size of the node you want to create. + // For more information about supported accelerator types for each TPU version, + // see https://cloud.google.com/tpu/docs/system-architecture-tpu-vm#versions. + const tpuType = 'v2-8'; + + // Software version that specifies the version of the node runtime to install. For more information, + // see https://cloud.google.com/tpu/docs/runtimes + const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + + async function callCreateQueuedResourceTimeBound() { + // Create a node + const node = new Node({ + name: nodeName, + zone, + acceleratorType: tpuType, + runtimeVersion: tpuSoftwareVersion, + // Define network + networkConfig: new NetworkConfig({ + enableExternalIps: true, + network: `projects/${projectId}/global/networks/${networkName}`, + subnetwork: `projects/${projectId}/regions/${region}/subnetworks/${networkName}`, + }), + queuedResource: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + }); + + // Define parent for requests + const parent = `projects/${projectId}/locations/${zone}`; + + // Create queued resource + const queuedResource = new QueuedResource({ + name: queuedResourceName, + tpu: { + nodeSpec: [ + { + parent, + node, + nodeId: nodeName, + }, + ], + }, + queueingPolicy: new QueuedResource.QueueingPolicy({ + // You can specify a duration after which a resource should be allocated. + validAfterDuration: { + // format: hour * 3600s + seconds: 6 * 3600, + }, + // You can specify how long a queued resource request remains valid. + // validUntilDuration: { + // // format: hour * 3600s + // seconds: 6 * 3600, + // }, + // You can specify a time after which a resource should be allocated. + // validAfterTime: { + // // format: new Date('YOUR_TIMESTAMP').getTime() / 1000 + // seconds: new Date('2024-10-25T11:45:00Z').getTime() / 1000, + // }, + // You can specify a time before which the resource should be allocated. + // validUntilTime: { + // // format: new Date('YOUR_TIMESTAMP').getTime() / 1000 + // seconds: new Date('2024-10-25T11:45:00Z').getTime() / 1000, + // }, + // You can specify an allocation interval. `startTime` specifies the beginning of the allocation interval + // and `endTime` specifies the end of the allocation interval. + // validInterval: { + // // format: new Date('YOUR_TIMESTAMP').getTime() / 1000 + // startTime: { + // seconds: new Date('2024-10-25T15:45:00Z').getTime() / 1000, + // }, + // endTime: { + // seconds: new Date('2024-10-26T11:45:00Z').getTime() / 1000, + // }, + // }, + }), + }); + + const request = { + parent: `projects/${projectId}/locations/${zone}`, + queuedResource, + queuedResourceId: queuedResourceName, + }; + + const [operation] = await tpuClient.createQueuedResource(request); + + // Wait for the create operation to complete. + const [response] = await operation.promise(); + + // You can wait until TPU Node is READY, + // and check its status using getTpuVm() from `tpu_vm_get` sample. + return response; + } + return await callCreateQueuedResourceTimeBound(); + // [END tpu_queued_resources_time_bound] +} + +module.exports = main; + +// TODO(developer): Uncomment below lines before running the sample. +// main(...process.argv.slice(2)).catch(err => { +// console.error(err); +// process.exitCode = 1; +// }); diff --git a/tpu/test/createQueuedResourceNetwork.test.js b/tpu/test/createQueuedResourceNetwork.test.js new file mode 100644 index 0000000000..df460f13c4 --- /dev/null +++ b/tpu/test/createQueuedResourceNetwork.test.js @@ -0,0 +1,81 @@ +/* + * 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 + * + * 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'; + +const assert = require('node:assert/strict'); +const {beforeEach, afterEach, describe, it} = require('mocha'); +const sinon = require('sinon'); +const createQueuedResourceNetwork = require('../queuedResources/createQueuedResourceNetwork.js'); + +describe('TPU queued resource with specified network', async () => { + const queuedResourceName = 'queued-resource-1'; + const nodeName = 'node-name-1'; + const zone = 'us-central1-a'; + const projectId = 'project_id'; + let tpuClientMock; + + beforeEach(() => { + tpuClientMock = { + getProjectId: sinon.stub().resolves(projectId), + }; + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should create queued resource', async () => { + tpuClientMock.createQueuedResource = sinon.stub().resolves([ + { + promise: sinon.stub().resolves([ + { + name: queuedResourceName, + }, + ]), + }, + ]); + + const response = await createQueuedResourceNetwork(tpuClientMock); + + sinon.assert.calledWith( + tpuClientMock.createQueuedResource, + sinon.match({ + parent: `projects/${projectId}/locations/${zone}`, + queuedResource: { + name: queuedResourceName, + tpu: { + nodeSpec: [ + sinon.match({ + parent: `projects/${projectId}/locations/${zone}`, + node: { + networkConfig: { + network: `projects/${projectId}/global/networks/compute-tpu-network`, + subnetwork: `projects/${projectId}/regions/us-central1/subnetworks/compute-tpu-network`, + enableExternalIps: true, + }, + }, + nodeId: nodeName, + }), + ], + }, + }, + queuedResourceId: queuedResourceName, + }) + ); + assert(response.name.includes(queuedResourceName)); + }); +}); diff --git a/tpu/test/createQueuedResourceStartupScript.test.js b/tpu/test/createQueuedResourceStartupScript.test.js new file mode 100644 index 0000000000..60c587e303 --- /dev/null +++ b/tpu/test/createQueuedResourceStartupScript.test.js @@ -0,0 +1,77 @@ +/* + * 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 + * + * 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'; + +const assert = require('node:assert/strict'); +const {beforeEach, afterEach, describe, it} = require('mocha'); +const sinon = require('sinon'); +const createQueuedResourceStartupScript = require('../queuedResources/createQueuedResourceStartupScript.js'); + +describe('TPU queued resource with start-up script', async () => { + const queuedResourceName = 'queued-resource-1'; + const nodeName = 'node-name-1'; + const zone = 'us-central1-a'; + const projectId = 'project_id'; + let tpuClientMock; + + beforeEach(() => { + tpuClientMock = { + getProjectId: sinon.stub().resolves(projectId), + }; + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should create queued resource', async () => { + tpuClientMock.createQueuedResource = sinon.stub().resolves([ + { + promise: sinon.stub().resolves([ + { + name: queuedResourceName, + }, + ]), + }, + ]); + + const response = await createQueuedResourceStartupScript(tpuClientMock); + + sinon.match({ + parent: `projects/${projectId}/locations/${zone}`, + queuedResource: { + name: queuedResourceName, + tpu: { + nodeSpec: [ + { + parent: `projects/${projectId}/locations/${zone}`, + node: { + metadata: { + 'startup-script': + '#!/bin/bash\n echo "Hello World" > /var/log/hello.log\n sudo pip3 install --upgrade numpy >> /var/log/hello.log 2>&1', + }, + }, + nodeId: nodeName, + }, + ], + }, + }, + queuedResourceId: queuedResourceName, + }); + assert(response.name.includes(queuedResourceName)); + }); +}); diff --git a/tpu/test/createQueuedResourceTimeBound.test.js b/tpu/test/createQueuedResourceTimeBound.test.js new file mode 100644 index 0000000000..43b6dc8d2f --- /dev/null +++ b/tpu/test/createQueuedResourceTimeBound.test.js @@ -0,0 +1,69 @@ +/* + * 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 + * + * 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'; + +const assert = require('node:assert/strict'); +const {beforeEach, afterEach, describe, it} = require('mocha'); +const sinon = require('sinon'); +const createQueuedResourceTimeBound = require('../queuedResources/createQueuedResourceTimeBound.js'); + +describe('TPU time bound queued resource', async () => { + const queuedResourceName = 'queued-resource-1'; + const zone = 'us-central1-a'; + const projectId = 'project_id'; + let tpuClientMock; + + beforeEach(() => { + tpuClientMock = { + getProjectId: sinon.stub().resolves(projectId), + }; + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should create queued resource', async () => { + tpuClientMock.createQueuedResource = sinon.stub().resolves([ + { + promise: sinon.stub().resolves([ + { + name: queuedResourceName, + }, + ]), + }, + ]); + + const response = await createQueuedResourceTimeBound(tpuClientMock); + + sinon.assert.calledWith( + tpuClientMock.createQueuedResource, + sinon.match({ + parent: `projects/${projectId}/locations/${zone}`, + queuedResource: { + queueingPolicy: { + validAfterDuration: { + seconds: 6 * 3600, + }, + }, + }, + queuedResourceId: 'queued-resource-1', + }) + ); + assert(response.name.includes(queuedResourceName)); + }); +});