diff --git a/tpu/package.json b/tpu/package.json index 0c9fe9d005..44140e7f0b 100644 --- a/tpu/package.json +++ b/tpu/package.json @@ -21,27 +21,4 @@ "c8": "^10.0.0", "mocha": "^10.0.0" } -} -{ - "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" - } -} +} \ No newline at end of file diff --git a/tpu/queuedResources/createQueuedResource.js b/tpu/queuedResources/createQueuedResource.js index e8ab1484d6..141f9d5e1c 100644 --- a/tpu/queuedResources/createQueuedResource.js +++ b/tpu/queuedResources/createQueuedResource.js @@ -16,24 +16,20 @@ 'use strict'; -async function main( - nodeName, - queuedResourceName, - zone, - tpuType, - tpuSoftwareVersion -) { +async function main(tpuClient) { // [START tpu_queued_resources_create] - // Import the TPU library - const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + // 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 - const tpuClient = new TpuClient(); + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); /** - * TODO(developer): Update/uncomment these variables before running the sample. + * TODO(developer): Update 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(); @@ -41,28 +37,28 @@ async function main( // 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 region of the subnetwork, that you want the node to connect to. + const region = 'us-central1'; // The name for your queued resource. - // queuedResourceName = 'queued-resource-1'; + const queuedResourceName = 'queued-resource-1'; // The name for your node. - // nodeName = 'node-name-1'; + 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 - // zone = 'europe-west4-a'; + const zone = `${region}-f`; // 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'; + 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 - // tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; async function callCreateQueuedResource() { // Create a node @@ -108,17 +104,21 @@ async function main( const [operation] = await tpuClient.createQueuedResource(request); // Wait for the create operation to complete. - await operation.promise(); + const [response] = await operation.promise(); // You can wait until TPU Node is READY, - // and check its status using getTpuVm() from `tpu_vm_get` sample. + // and check its status using callGetTpuVm() from `tpu_vm_get` sample. console.log(`Queued resource ${queuedResourceName} created.`); + return response; } - await callCreateQueuedResource(); + return await callCreateQueuedResource(); // [END tpu_queued_resources_create] } -main(...process.argv.slice(2)).catch(err => { - console.error(err); - process.exitCode = 1; -}); +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/deleteQueuedResource.js b/tpu/queuedResources/deleteQueuedResource.js index a3e03cc821..2db83ef165 100644 --- a/tpu/queuedResources/deleteQueuedResource.js +++ b/tpu/queuedResources/deleteQueuedResource.js @@ -16,25 +16,27 @@ 'use strict'; -async function main(queuedResourceName, zone) { +async function main(tpuClient) { // [START tpu_queued_resources_delete] - // Import the TPU library - const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; // Instantiate a tpuClient - const tpuClient = new TpuClient(); + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); /** - * TODO(developer): Update/uncomment these variables before running the sample. + * TODO(developer): Update 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'; + const queuedResourceName = 'queued-resource-1'; // The zone of your queued resource. - // zone = 'europe-west4-a'; + const zone = 'us-central1-f'; async function callDeleteTpuVM(nodeName) { const request = { @@ -55,8 +57,8 @@ async function main(queuedResourceName, zone) { }; // Retrive node name - const [response] = await tpuClient.getQueuedResource(request); - const nodeName = response.tpu.nodeSpec[0].nodeId; + const [queuedResource] = await tpuClient.getQueuedResource(request); + const nodeName = queuedResource.tpu.nodeSpec[0].nodeId; // Before deleting the queued resource it is required to delete the TPU VM. await callDeleteTpuVM(nodeName); @@ -64,15 +66,19 @@ async function main(queuedResourceName, zone) { const [operation] = await tpuClient.deleteQueuedResource(request); // Wait for the delete operation to complete. - await operation.promise(); + const [response] = await operation.promise(); console.log(`Queued resource ${queuedResourceName} deleted.`); + return response; } - await callDeleteQueuedResource(); + return await callDeleteQueuedResource(); // [END tpu_queued_resources_delete] } -main(...process.argv.slice(2)).catch(err => { - console.error(err); - process.exitCode = 1; -}); +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/forceDeleteQueuedResource.js b/tpu/queuedResources/forceDeleteQueuedResource.js index e842c39e26..066d40c1d1 100644 --- a/tpu/queuedResources/forceDeleteQueuedResource.js +++ b/tpu/queuedResources/forceDeleteQueuedResource.js @@ -16,25 +16,27 @@ 'use strict'; -async function main(queuedResourceName, zone) { +async function main(tpuClient) { // [START tpu_queued_resources_delete_force] - // Import the TPU library - const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; // Instantiate a tpuClient - const tpuClient = new TpuClient(); + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); /** - * TODO(developer): Update/uncomment these variables before running the sample. + * TODO(developer): Update 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'; + const queuedResourceName = 'queued-resource-1'; // The zone of your queued resource. - // zone = 'europe-west4-a'; + const zone = 'us-central1-f'; async function callForceDeleteQueuedResource() { const request = { @@ -45,15 +47,19 @@ async function main(queuedResourceName, zone) { const [operation] = await tpuClient.deleteQueuedResource(request); // Wait for the delete operation to complete. - await operation.promise(); + const [response] = await operation.promise(); console.log(`Queued resource ${queuedResourceName} deletion forced.`); + return response; } - await callForceDeleteQueuedResource(); + return await callForceDeleteQueuedResource(); // [END tpu_queued_resources_delete_force] } -main(...process.argv.slice(2)).catch(err => { - console.error(err); - process.exitCode = 1; -}); +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/getQueuedResource.js b/tpu/queuedResources/getQueuedResource.js index 7a84ed467e..7a243f187a 100644 --- a/tpu/queuedResources/getQueuedResource.js +++ b/tpu/queuedResources/getQueuedResource.js @@ -16,25 +16,27 @@ 'use strict'; -async function main(queuedResourceName, zone) { +async function main(tpuClient) { // [START tpu_queued_resources_get] - // Import the TPU library - const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; // Instantiate a tpuClient - const tpuClient = new TpuClient(); + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); /** - * TODO(developer): Update/uncomment these variables before running the sample. + * TODO(developer): Update these variables before running the sample. */ // Project ID or project number of the Google Cloud project, where you want to retrive node. const projectId = await tpuClient.getProjectId(); // The name of queued resource. - // queuedResourceName = 'queued-resource-1'; + const queuedResourceName = 'queued-resource-1'; // The zone of your queued resource. - // zone = 'europe-west4-a'; + const zone = 'us-central1-f'; async function callGetQueuedResource() { const request = { @@ -43,14 +45,17 @@ async function main(queuedResourceName, zone) { const [response] = await tpuClient.getQueuedResource(request); - console.log(JSON.stringify(response)); console.log(`Queued resource ${queuedResourceName} retrived.`); + return response; } - await callGetQueuedResource(); + return await callGetQueuedResource(); // [END tpu_queued_resources_get] } -main(...process.argv.slice(2)).catch(err => { - console.error(err); - process.exitCode = 1; -}); +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/getQueuedResourcesList.js b/tpu/queuedResources/getQueuedResourcesList.js index a553aa20c5..21815db23e 100644 --- a/tpu/queuedResources/getQueuedResourcesList.js +++ b/tpu/queuedResources/getQueuedResourcesList.js @@ -16,13 +16,15 @@ 'use strict'; -async function main(zone) { +async function main(tpuClient) { // [START tpu_queued_resources_list] - // Import the TPU library - const {TpuClient} = require('@google-cloud/tpu').v2alpha1; + // Import the TPUClient + // TODO(developer): Uncomment below line before running the sample. + // const {TpuClient} = require('@google-cloud/tpu').v2alpha1; // Instantiate a tpuClient - const tpuClient = new TpuClient(); + // TODO(developer): Uncomment below line before running the sample. + // tpuClient = new TpuClient(); /** * TODO(developer): Update/uncomment these variables before running the sample. @@ -31,7 +33,7 @@ async function main(zone) { const projectId = await tpuClient.getProjectId(); // The zone from which the Queued Resources are retrived. - // zone = 'europe-west4-a'; + const zone = 'us-central1-f'; async function callGetQueuedResourcesList() { const request = { @@ -40,13 +42,16 @@ async function main(zone) { const [response] = await tpuClient.listQueuedResources(request); - console.log(JSON.stringify(response)); + return response; } - await callGetQueuedResourcesList(); + return await callGetQueuedResourcesList(); // [END tpu_queued_resources_list] } -main(...process.argv.slice(2)).catch(err => { - console.error(err); - process.exitCode = 1; -}); +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/forceDeleteQueuedResource.test.js b/tpu/test/forceDeleteQueuedResource.test.js index 8429f01d4d..7887f6a4bb 100644 --- a/tpu/test/forceDeleteQueuedResource.test.js +++ b/tpu/test/forceDeleteQueuedResource.test.js @@ -16,42 +16,48 @@ '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, '..'); +const {beforeEach, afterEach, describe, it} = require('mocha'); +const sinon = require('sinon'); +const forceDeleteQueuedResource = require('../queuedResources/forceDeleteQueuedResource.js'); describe('TPU queued resource force deletion', async () => { - const queuedResourceName = `queued-resource-force-delete-${Math.floor(Math.random() * 1000 + 1)}`; - const nodePrefix = 'node-force-delete-2a2b3c'; - const nodeName = `${nodePrefix}${Math.floor(Math.random() * 1000 + 1)}`; - const zone = 'us-central1-c'; - const tpuType = 'v2-8'; - const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; - - it('should force queued resource deletion', () => { - // Create queued resource - execSync( - `node ./queuedResources/createQueuedResource.js ${nodeName} ${queuedResourceName} ${zone} ${tpuType} ${tpuSoftwareVersion}`, - { - cwd, - } - ); + const queuedResourceName = 'queued-resource-1'; + const zone = 'us-central1-f'; + const projectId = 'project_id'; + let tpuClientMock; + + beforeEach(() => { + tpuClientMock = { + getProjectId: sinon.stub().resolves(projectId), + }; + }); - const response = execSync( - `node ./queuedResources/forceDeleteQueuedResource.js ${queuedResourceName} ${zone}`, + afterEach(() => { + sinon.restore(); + }); + + it('should force queued resource deletion', async () => { + const message = `Queued resource ${queuedResourceName} deletion forced.`; + tpuClientMock.deleteQueuedResource = sinon.stub().resolves([ { - cwd, - } - ); + promise: sinon.stub().resolves([ + { + message, + }, + ]), + }, + ]); + + const response = await forceDeleteQueuedResource(tpuClientMock); - assert( - response.includes( - `Queued resource ${queuedResourceName} deletion forced.` - ) + sinon.assert.calledWith( + tpuClientMock.deleteQueuedResource, + sinon.match({ + name: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + force: true, + }) ); + assert(response.message.includes(message)); }); }); diff --git a/tpu/test/queuedResource.test.js b/tpu/test/queuedResource.test.js index 0467172c4f..d4c7e68d81 100644 --- a/tpu/test/queuedResource.test.js +++ b/tpu/test/queuedResource.test.js @@ -16,93 +16,145 @@ 'use strict'; -const path = require('path'); const assert = require('node:assert/strict'); -const {describe, it} = require('mocha'); -const cp = require('child_process'); -const {TpuClient} = require('@google-cloud/tpu').v2alpha1; - -const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); -const cwd = path.join(__dirname, '..'); - -async function waitForTPUCreation(nodeName, zone) { - const tpuClient = new TpuClient(); - const projectId = await tpuClient.getProjectId(); - - // Give a time to start process of creating TPU Node - await new Promise(resolve => setTimeout(resolve, 60000)); - - const getNodeRequest = { - name: `projects/${projectId}/locations/${zone}/nodes/${nodeName}`, - }; - - console.log(`Waiting for TPU node ${nodeName} to become ready...`); - - let state; - - while (state !== 'READY') { - try { - state = (await tpuClient.getNode(getNodeRequest))[0].state; - // Wait another minute to try - await new Promise(resolve => setTimeout(resolve, 60000)); - } catch (err) { - console.log('TPU node not ready'); - // Wait another minute to try - await new Promise(resolve => setTimeout(resolve, 60000)); - } - } -} +const {beforeEach, afterEach, describe, it} = require('mocha'); +const sinon = require('sinon'); +const createQueuedResource = require('../queuedResources/createQueuedResource.js'); +const getQueuedResource = require('../queuedResources/getQueuedResource.js'); +const getQueuedResourcesList = require('../queuedResources/getQueuedResourcesList.js'); +const deleteQueuedResource = require('../queuedResources/deleteQueuedResource.js'); describe('TPU queued resource', () => { - 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 queuedResourceName = 'queued-resource-1'; + const nodeName = 'node-name-1'; const zone = 'us-central1-f'; - const tpuType = 'v2-8'; - const tpuSoftwareVersion = 'tpu-vm-tf-2.14.1'; + const projectId = 'project_id'; + let tpuClientMock; + + beforeEach(() => { + tpuClientMock = { + getProjectId: sinon.stub().resolves(projectId), + }; + }); + + afterEach(() => { + sinon.restore(); + }); it('should create a new queued resource', async () => { - const response = execSync( - `node ./queuedResources/createQueuedResource.js ${nodeName} ${queuedResourceName} ${zone} ${tpuType} ${tpuSoftwareVersion}`, + tpuClientMock.createQueuedResource = sinon.stub().resolves([ { - cwd, - } + promise: sinon.stub().resolves([ + { + name: queuedResourceName, + }, + ]), + }, + ]); + + const response = await createQueuedResource(tpuClientMock); + + sinon.assert.calledWith( + tpuClientMock.createQueuedResource, + sinon.match({ + parent: `projects/${projectId}/locations/${zone}`, + queuedResource: { + name: queuedResourceName, + }, + queuedResourceId: queuedResourceName, + }) ); - assert(response.includes(`Queued resource ${queuedResourceName} created.`)); + assert(response.name.includes(queuedResourceName)); }); - it('should return requested queued resource', () => { - const response = execSync( - `node ./queuedResources/getQueuedResource.js ${queuedResourceName} ${zone}`, + it('should return requested queued resource', async () => { + tpuClientMock.getQueuedResource = sinon.stub().resolves([ { - cwd, - } - ); + name: queuedResourceName, + }, + ]); - assert( - response.includes(`Queued resource ${queuedResourceName} retrived.`) + const response = await getQueuedResource(tpuClientMock); + + sinon.assert.calledWith( + tpuClientMock.getQueuedResource, + sinon.match({ + name: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + }) ); + assert(response.name.includes(queuedResourceName)); }); - it('should return list of queued resources', () => { - const response = JSON.parse( - execSync(`node ./queuedResources/getQueuedResourcesList.js ${zone}`, { - cwd, + it('should return list of queued resources', async () => { + const queuedResources = [ + { + name: queuedResourceName, + }, + { + name: 'queued-resource-2', + }, + ]; + tpuClientMock.listQueuedResources = sinon + .stub() + .resolves([queuedResources]); + + const response = await getQueuedResourcesList(tpuClientMock); + + sinon.assert.calledWith( + tpuClientMock.listQueuedResources, + sinon.match({ + parent: `projects/${projectId}/locations/${zone}`, }) ); - - assert(Array.isArray(response)); + assert.deepEqual(response, queuedResources); }); it('should delete queued resource', async () => { - // Wait until queued resource is ready to delete. - await waitForTPUCreation(nodeName, zone); - const response = execSync( - `node ./queuedResources/deleteQueuedResource.js ${queuedResourceName} ${zone}`, + tpuClientMock.getQueuedResource = sinon.stub().resolves([ + { + name: queuedResourceName, + tpu: { + nodeSpec: [ + { + nodeId: nodeName, + }, + ], + }, + }, + ]); + tpuClientMock.deleteNode = sinon.stub().resolves([ { - cwd, - } + promise: sinon.stub().resolves([]), + }, + ]); + tpuClientMock.deleteQueuedResource = sinon.stub().resolves([ + { + promise: sinon.stub().resolves([ + { + message: `Queued resource ${queuedResourceName} deleted.`, + }, + ]), + }, + ]); + + const response = await deleteQueuedResource(tpuClientMock); + + sinon.assert.calledWith( + tpuClientMock.getQueuedResource, + sinon.match({ + name: `projects/${projectId}/locations/${zone}/queuedResources/${queuedResourceName}`, + }) + ); + sinon.assert.calledWith( + tpuClientMock.deleteNode, + sinon.match({ + name: `projects/${projectId}/locations/${zone}/nodes/${nodeName}`, + }) + ); + assert( + response.message.includes( + `Queued resource ${queuedResourceName} deleted.` + ) ); - assert(response.includes(`Queued resource ${queuedResourceName} deleted.`)); }); });