diff --git a/compute/resetInstance.js b/compute/resetInstance.js new file mode 100644 index 0000000000..622b5eafa2 --- /dev/null +++ b/compute/resetInstance.js @@ -0,0 +1,60 @@ +// 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. + +/** + * Resets a stopped Google Compute Engine instance (with unencrypted disks). + * + * @param {string} projectId - project ID or project number of the Cloud project your instance belongs to. + * @param {string} zone - name of the zone your instance belongs to. + * @param {string} instanceName - name of the instance your want to reset. + */ +function main(projectId, zone, instanceName) { + // [START compute_reset_instance] + /** + * TODO(developer): Uncomment and replace these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const zone = 'europe-central2-b' + // const instanceName = 'YOUR_INSTANCE_NAME' + + const compute = require('@google-cloud/compute'); + + async function resetInstance() { + const instancesClient = new compute.InstancesClient(); + + const [response] = await instancesClient.reset({ + project: projectId, + zone, + instance: instanceName, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log('Instance reset.'); + } + + resetInstance(); + // [END compute_reset_instance] +} + +main(...process.argv.slice(2)); diff --git a/compute/startInstance.js b/compute/startInstance.js new file mode 100644 index 0000000000..289d3b8a76 --- /dev/null +++ b/compute/startInstance.js @@ -0,0 +1,60 @@ +// 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. + +/** + * Starts a stopped Google Compute Engine instance (with unencrypted disks). + * + * @param {string} projectId - project ID or project number of the Cloud project your instance belongs to. + * @param {string} zone - name of the zone your instance belongs to. + * @param {string} instanceName - name of the instance your want to start. + */ +function main(projectId, zone, instanceName) { + // [START compute_start_instance] + /** + * TODO(developer): Uncomment and replace these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const zone = 'europe-central2-b' + // const instanceName = 'YOUR_INSTANCE_NAME' + + const compute = require('@google-cloud/compute'); + + async function startInstance() { + const instancesClient = new compute.InstancesClient(); + + const [response] = await instancesClient.start({ + project: projectId, + zone, + instance: instanceName, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log('Instance started.'); + } + + startInstance(); + // [END compute_start_instance] +} + +main(...process.argv.slice(2)); diff --git a/compute/startInstanceWithEncKey.js b/compute/startInstanceWithEncKey.js new file mode 100644 index 0000000000..f83f0bba48 --- /dev/null +++ b/compute/startInstanceWithEncKey.js @@ -0,0 +1,80 @@ +// 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. + +/** + * Starts a stopped Google Compute Engine instance (with encrypted disks). + * + * @param {string} projectId - project ID or project number of the Cloud project your instance belongs to. + * @param {string} zone - name of the zone your instance belongs to. + * @param {string} instanceName - name of the instance your want to start. + * @param {string} key - stringrepresenting a raw base64 encoded key to your machines boot disk. + * For more information about disk encryption see: + * https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications + */ +function main(projectId, zone, instanceName, key) { + // [START compute_start_enc_instance] + /** + * TODO(developer): Uncomment and replace these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const zone = 'europe-central2-b' + // const instanceName = 'YOUR_INSTANCE_NAME' + // const key = 'YOUR_KEY_STRING' + + const compute = require('@google-cloud/compute'); + + async function startInstanceWithEncryptionKey() { + const instancesClient = new compute.InstancesClient(); + + const [instance] = await instancesClient.get({ + project: projectId, + zone, + instance: instanceName, + }); + + const [response] = await instancesClient.startWithEncryptionKey({ + project: projectId, + zone, + instance: instanceName, + instancesStartWithEncryptionKeyRequestResource: { + disks: [ + { + source: instance.disks[0].source, + diskEncryptionKey: { + rawKey: key, + }, + }, + ], + }, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log('Instance with encryption key started.'); + } + + startInstanceWithEncryptionKey(); + // [END compute_start_enc_instance] +} + +main(...process.argv.slice(2)); diff --git a/compute/stopInstance.js b/compute/stopInstance.js new file mode 100644 index 0000000000..1cf188a9a2 --- /dev/null +++ b/compute/stopInstance.js @@ -0,0 +1,60 @@ +// 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. + +/** + * Stops a started Google Compute Engine instance. + * + * @param {string} projectId - project ID or project number of the Cloud project your instance belongs to. + * @param {string} zone - name of the zone your instance belongs to. + * @param {string} instanceName - name of the instance your want to stop. + */ +function main(projectId, zone, instanceName) { + // [START compute_stop_instance] + /** + * TODO(developer): Uncomment and replace these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const zone = 'europe-central2-b' + // const instanceName = 'YOUR_INSTANCE_NAME' + + const compute = require('@google-cloud/compute'); + + async function stopInstance() { + const instancesClient = new compute.InstancesClient(); + + const [response] = await instancesClient.stop({ + project: projectId, + zone, + instance: instanceName, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log('Instance stopped.'); + } + + stopInstance(); + // [END compute_stop_instance] +} + +main(...process.argv.slice(2)); diff --git a/compute/test/samples.test.js b/compute/test/samples.test.js index 29ace1c7d3..345dc738dd 100644 --- a/compute/test/samples.test.js +++ b/compute/test/samples.test.js @@ -15,6 +15,7 @@ 'use strict'; const compute = require('@google-cloud/compute'); +const computeProtos = compute.protos.google.cloud.compute.v1; const {Storage} = require('@google-cloud/storage'); const {describe, it} = require('mocha'); @@ -194,4 +195,122 @@ describe('samples', () => { assert.match(output, /Page 2/); }); }); + + const getInstance = async (projectId, zone, instanceName) => { + const [instance] = await instancesClient.get({ + project: projectId, + zone, + instance: instanceName, + }); + return instance; + }; + + describe('start/stop instances', () => { + it('should start/stop instances', async () => { + const projectId = await instancesClient.getProjectId(); + const newInstanceName = `gcloud-test-instance-${uuid.v4().split('-')[0]}`; + + execSync(`node createInstance ${projectId} ${zone} ${newInstanceName}`); + + let instance = await getInstance(projectId, zone, newInstanceName); + assert.equal(instance.status, 'RUNNING'); + + const stopOutput = execSync( + `node stopInstance ${projectId} ${zone} ${newInstanceName}` + ); + assert.match(stopOutput, /Instance stopped/); + + instance = await getInstance(projectId, zone, newInstanceName); + assert.equal(instance.status, 'TERMINATED'); + + const startOutput = execSync( + `node startInstance ${projectId} ${zone} ${newInstanceName}` + ); + assert.match(startOutput, /Instance started/); + + instance = await getInstance(projectId, zone, newInstanceName); + assert.equal(instance.status, 'RUNNING'); + + execSync(`node deleteInstance ${projectId} ${zone} ${newInstanceName}`); + }); + + it('should start/stop instances with encrypted disks', async () => { + const projectId = await instancesClient.getProjectId(); + const newInstanceName = `gcloud-test-instance-${uuid.v4().split('-')[0]}`; + + const KEY = uuid.v4().split('-').join(''); + const KEY_BASE64 = Buffer.from(KEY).toString('base64'); + + const [response] = await instancesClient.insert({ + instanceResource: { + name: newInstanceName, + disks: [ + { + initializeParams: { + diskSizeGb: '10', + sourceImage: + 'projects/debian-cloud/global/images/family/debian-10', + }, + autoDelete: true, + boot: true, + type: computeProtos.AttachedDisk.Type.PERSISTENT, + diskEncryptionKey: { + rawKey: KEY_BASE64, + }, + }, + ], + machineType: `zones/${zone}/machineTypes/n1-standard-1`, + networkInterfaces: [ + { + name: 'global/networks/default', + }, + ], + }, + project: projectId, + zone, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + const stopOutput = execSync( + `node stopInstance ${projectId} ${zone} ${newInstanceName}` + ); + assert.match(stopOutput, /Instance stopped/); + + let instance = await getInstance(projectId, zone, newInstanceName); + assert.equal(instance.status, 'TERMINATED'); + + const startOutput = execSync( + `node startInstanceWithEncKey ${projectId} ${zone} ${newInstanceName} ${KEY_BASE64}` + ); + assert.match(startOutput, /Instance with encryption key started/); + + instance = await getInstance(projectId, zone, newInstanceName); + assert.equal(instance.status, 'RUNNING'); + + execSync(`node deleteInstance ${projectId} ${zone} ${newInstanceName}`); + }); + + it('should reset instance', async () => { + const projectId = await instancesClient.getProjectId(); + const newInstanceName = `gcloud-test-instance-${uuid.v4().split('-')[0]}`; + + execSync(`node createInstance ${projectId} ${zone} ${newInstanceName}`); + + const resetOutput = execSync( + `node resetInstance ${projectId} ${zone} ${newInstanceName}` + ); + assert.match(resetOutput, /Instance reset/); + + execSync(`node deleteInstance ${projectId} ${zone} ${newInstanceName}`); + }); + }); });