diff --git a/.github/workflows/tpu.yaml b/.github/workflows/tpu.yaml new file mode 100644 index 00000000000..311d65db710 --- /dev/null +++ b/.github/workflows/tpu.yaml @@ -0,0 +1,54 @@ +# 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. + +name: tpu +on: + push: + branches: + - main + paths: + - 'tpu/**' + - '.github/workflows/tpu.yaml' + - '.github/workflows/test.yaml' + pull_request: + types: + - opened + - reopened + - synchronize + - labeled + paths: + - 'tpu/**' + - '.github/workflows/tpu.yaml' + - '.github/workflows/test.yaml' + schedule: + - cron: '0 0 * * 0' +jobs: + test: + # Ref: https://github.com/google-github-actions/auth#usage + permissions: + contents: 'read' + id-token: 'write' + if: github.event.action != 'labeled' || github.event.label.name == 'actions:force-run' + uses: ./.github/workflows/test.yaml + with: + name: 'tpu' + path: 'tpu' + flakybot: + # Ref: https://github.com/google-github-actions/auth#usage + permissions: + contents: 'read' + id-token: 'write' + if: github.event_name == 'schedule' && always() # always() submits logs even if tests fail + uses: ./.github/workflows/flakybot.yaml + needs: [test] \ No newline at end of file diff --git a/.github/workflows/utils/workflows.json b/.github/workflows/utils/workflows.json index ff954978f83..49884faf2d6 100644 --- a/.github/workflows/utils/workflows.json +++ b/.github/workflows/utils/workflows.json @@ -90,6 +90,7 @@ "speech", "talent", "texttospeech", + "tpu", "translate", "video-intelligence", "vision/productSearch", diff --git a/CODEOWNERS b/CODEOWNERS index beba1e13c79..d679277d5de 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -24,6 +24,7 @@ recaptcha_enterprise @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs- 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 service-directory @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers +tpu @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers webrisk @GoogleCloudPlatform/dee-infra @GoogleCloudPlatform/nodejs-samples-reviewers @GoogleCloudPlatform/cloud-samples-reviewers # SoDa teams diff --git a/tpu/package.json b/tpu/package.json new file mode 100644 index 00000000000..3b93a5d7fac --- /dev/null +++ b/tpu/package.json @@ -0,0 +1,23 @@ +{ + "name": "nodejs-docs-samples-tpu", + "license": "Apache-2.0", + "author": "Google Inc.", + "engines": { + "node": ">=16.0.0" + }, + "repository": "googleapis/nodejs-tpu", + "private": true, + "files": [ + "*.js" + ], + "scripts": { + "test": "c8 mocha -p -j 2 test --timeout 1200000" + }, + "dependencies": { + "@google-cloud/tpu": "^3.5.0" + }, + "devDependencies": { + "c8": "^10.0.0", + "mocha": "^10.0.0" + } +} diff --git a/tpu/queuedResource/createQueuedResource.js b/tpu/queuedResource/createQueuedResource.js new file mode 100644 index 00000000000..8dd06f77623 --- /dev/null +++ b/tpu/queuedResource/createQueuedResource.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( + nodeName, + queuedResourceName, + zone, + tpuType, + tpuSoftwareVersion +) { + // [START tpu_queued_resources_create] + // Import the TPU library + const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + const {Node, NetworkConfig, QueuedResource} = + require('@google-cloud/tpu').protos.google.cloud.tpu.v2alpha1; + + // Instantiate a tpuClient + const 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 = 'europe-west4'; + + // The name for your queued resource. + // queuedResourceName = 'queued-resource-1'; + + // The name for your node. + // 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 + // zone = 'europe-west4-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. + // 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 + // tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + + async function callCreateQueuedResource() { + // 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, + }, + ], + }, + // TODO(developer): Uncomment next line if you want to specify reservation. + // reservationName: 'reservation-name' + }); + + 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(); + + console.log(JSON.stringify(response)); + console.log(`Queued resource ${queuedResourceName} created.`); + } + await callCreateQueuedResource(); + // [END tpu_queued_resources_create] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/tpu/queuedResource/deleteQueuedResource.js b/tpu/queuedResource/deleteQueuedResource.js new file mode 100644 index 00000000000..04fe75fe1b1 --- /dev/null +++ b/tpu/queuedResource/deleteQueuedResource.js @@ -0,0 +1,59 @@ +/* + * 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(queuedResourceName, zone) { + // [START tpu_queued_resources_delete] + // Import the TPU library + const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + + // Instantiate a tpuClient + const 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 delete node. + const projectId = await tpuClient.getProjectId(); + + // The name of queued resource. + // queuedResourceName = 'queued-resource-1'; + + // The zone of your queued resource. + // zone = 'europe-west4-a'; + + async function callDeleteQueuedResource() { + const request = { + name: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + }; + + const [operation] = await tpuClient.deleteQueuedResource(request); + + // Wait for the delete operation to complete. + const [response] = await operation.promise(); + + console.log(JSON.stringify(response)); + console.log(`Queued resource ${queuedResourceName} deleted.`); + } + await callDeleteQueuedResource(); + // [END tpu_queued_resources_delete] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/tpu/queuedResource/forceDeleteQueuedResource.js b/tpu/queuedResource/forceDeleteQueuedResource.js new file mode 100644 index 00000000000..49b623572c9 --- /dev/null +++ b/tpu/queuedResource/forceDeleteQueuedResource.js @@ -0,0 +1,60 @@ +/* + * 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(queuedResourceName, zone) { + // [START tpu_queued_resources_delete_force] + // Import the TPU library + const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + + // Instantiate a tpuClient + const 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 delete node. + const projectId = await tpuClient.getProjectId(); + + // The name of queued resource. + // queuedResourceName = 'queued-resource-1'; + + // The zone of your queued resource. + // zone = 'europe-west4-a'; + + async function callForceDeleteQueuedResource() { + const request = { + name: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + force: true, + }; + + const [operation] = await tpuClient.deleteQueuedResource(request); + + // Wait for the delete operation to complete. + const [response] = await operation.promise(); + + console.log(JSON.stringify(response)); + console.log(`Queued resource ${queuedResourceName} deletion forced.`); + } + await callForceDeleteQueuedResource(); + // [END tpu_queued_resources_delete_force] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/tpu/test/.eslintrc b/tpu/test/.eslintrc new file mode 100644 index 00000000000..6db2a46c535 --- /dev/null +++ b/tpu/test/.eslintrc @@ -0,0 +1,3 @@ +--- +env: + mocha: true diff --git a/tpu/test/queuedResource.test.js b/tpu/test/queuedResource.test.js new file mode 100644 index 00000000000..3e1649be0a5 --- /dev/null +++ b/tpu/test/queuedResource.test.js @@ -0,0 +1,59 @@ +/* + * 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 path = require('path'); +const assert = require('node:assert/strict'); +const {describe, it} = require('mocha'); +const cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +describe('TPU queued resource', async () => { + const queuedResourceName = `queued-resource-name-1a2sdf${Math.floor(Math.random() * 1000 + 1)}`; + const nodePrefix = 'node-name-2a2b3c'; + const nodeName = `${nodePrefix}${Math.floor(Math.random() * 1000 + 1)}`; + const zone = 'europe-west4-a'; + const tpuType = 'v2-8'; + const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + + it('should create a new queued resource', () => { + const response = execSync( + `node ./queuedResource/createQueuedResource.js ${nodeName} ${queuedResourceName} ${zone} ${tpuType} ${tpuSoftwareVersion}`, + { + cwd, + } + ); + assert(response.includes(`Queued resource ${queuedResourceName} created.`)); + }); + + it('should force queued resource deletion', () => { + const response = execSync( + `node ./queuedResource/forceDeleteQueuedResource.js ${queuedResourceName} ${zone}`, + { + cwd, + } + ); + + assert( + response.includes( + `Queued resource ${queuedResourceName} deletion forced.` + ) + ); + }); +});