Skip to content
Open
22 changes: 13 additions & 9 deletions compute/reservations/createInstanceToConsumeAnyReservation.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,14 @@

async function main(instanceName) {
// [START compute_consume_any_matching_reservation]
// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a reservationsClient
const instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
* TODO(developer): Update/uncomment these variables before running the sample.
* TODO(developer): Customize the following variables before running the sample.
*/
// The ID of the project where you want to create instance.
const projectId = await instancesClient.getProjectId();
Expand All @@ -39,9 +36,10 @@ async function main(instanceName) {
// Machine type to use for VM.
const machineType = 'n1-standard-4';

// Create instance to consume reservation if their properties match the VM properties
async function callCreateInstanceToConsumeAnyReservation() {
// Describe the size and source image of the boot disk to attach to the instance.
// Uses a persistent disk so that data is preserved even if the VM is
// stopped or restarted.
const disk = new compute.Disk({
boot: true,
autoDelete: true,
Expand All @@ -52,17 +50,24 @@ async function main(instanceName) {
},
});

// Define networkInterface
// Use the default network for simplicity. In production environments,
// you may want to specify a custom network with specific firewall rules
// and security configurations.
const networkInterface = new compute.NetworkInterface({
name: 'global/networks/default',
});

// Define reservationAffinity
// Configure the instance to consume any available reservation that matches
// its requirements (CPU, memory, etc.). This is a reasonable default for cost
// optimization for long-running workloads. Consider changing depending on your
// specific needs or workloads.
const reservationAffinity = new compute.ReservationAffinity({
consumeReservationType: 'ANY_RESERVATION',
});

// Create an instance
// Set the minimum CPU platform to ensure compatibility with
// machine type and to take advantage of specific CPU features.
// Change this based on performance and workload needs
const instance = new compute.Instance({
name: instanceName,
machineType: `zones/${zone}/machineTypes/${machineType}`,
Expand All @@ -80,7 +85,6 @@ async function main(instanceName) {

let operation = response.latestResponse;

// Wait for the create instance operation to complete.
while (operation.status !== 'DONE') {
[operation] = await zoneOperationsClient.wait({
operation: operation.name,
Expand Down
120 changes: 120 additions & 0 deletions compute/reservations/createInstanceToConsumeSharedReservation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* 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(instancesClient, zoneOperationsClient) {
// [START compute_consume_specific_shared_reservation]
// Import the Compute library
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

/**
* TODO(developer): Uncomment reservationsClient and zoneOperationsClient before running the sample.
*/
// Instantiate an instancesClient
// instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
// zoneOperationsClient = new computeLib.ZoneOperationsClient();

/**
* TODO(developer): Update these variables before running the sample.
*/
// The ID of the project where instance will be consumed and created.
const reservationConsumerProjectId = 'reservation-consumer-project-id';
// The ID of the project where reservation is created.
const reservationOwnerProjectId = 'reservation-project-id';
// The name of the instance to create.
const instanceName = 'instance-01';
// The name of the reservation to consume.
// Ensure that the specificReservationRequired field in reservation properties is set to true.
const reservationName = 'reservation-1';
// Machine type to use for VM.
const machineType = 'n1-standard-1';
// The zone in which to create instance.
const zone = 'us-central1-a';

// Create instance to consume shared reservation
async function callCreateInstanceToConsumeSharedReservation() {
// Describe the size and source image of the boot disk to attach to the instance.
// Ensure that the VM's properties match the reservation's VM properties,
// including the zone, machine type (machine family, vCPUs, and memory),
// minimum CPU platform, GPU amount and type, and local SSD interface and size
const disk = new compute.Disk({
boot: true,
autoDelete: true,
type: 'PERSISTENT',
initializeParams: {
diskSizeGb: '10',
sourceImage: 'projects/debian-cloud/global/images/family/debian-12',
},
});

// Define networkInterface
const networkInterface = new compute.NetworkInterface({
name: 'global/networks/default',
});

// Define reservationAffinity
const reservationAffinity = new compute.ReservationAffinity({
consumeReservationType: 'SPECIFIC_RESERVATION',
key: 'compute.googleapis.com/reservation-name',
values: [
`projects/${reservationOwnerProjectId}/reservations/${reservationName}`,
],
});

// Create an instance
const instance = new compute.Instance({
name: instanceName,
machineType: `zones/${zone}/machineTypes/${machineType}`,
disks: [disk],
networkInterfaces: [networkInterface],
reservationAffinity,
});

const [response] = await instancesClient.insert({
project: reservationConsumerProjectId,
instanceResource: instance,
zone,
});

let operation = response.latestResponse;

// Wait for the create instance operation to complete.
while (operation.status !== 'DONE') {
[operation] = await zoneOperationsClient.wait({
operation: operation.name,
project: reservationConsumerProjectId,
zone: operation.zone.split('/').pop(),
});
}

console.log(`Instance ${instanceName} created from shared reservation.`);
return response;
}

return await callCreateInstanceToConsumeSharedReservation();
// [END compute_consume_specific_shared_reservation]
}

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;
// });
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function main(instanceName, reservationName) {
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a reservationsClient
// Instantiate an instancesClient
const instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function main(instanceName) {
const computeLib = require('@google-cloud/compute');
const compute = computeLib.protos.google.cloud.compute.v1;

// Instantiate a reservationsClient
// Instantiate an instancesClient
const instancesClient = new computeLib.InstancesClient();
// Instantiate a zoneOperationsClient
const zoneOperationsClient = new computeLib.ZoneOperationsClient();
Expand Down
5 changes: 4 additions & 1 deletion compute/test/consumeReservations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

const path = require('path');
const assert = require('node:assert/strict');
const {before, describe, it} = require('mocha');
const {before, after, describe, it} = require('mocha');
const cp = require('child_process');
const {ReservationsClient} = require('@google-cloud/compute').v1;
const {
Expand All @@ -40,6 +40,9 @@ describe('Consume reservations', async () => {

before(async () => {
projectId = await reservationsClient.getProjectId();
});

after(async () => {
// Cleanup resources
const instances = await getStaleVMInstances(instancePrefix);
await Promise.all(
Expand Down
16 changes: 2 additions & 14 deletions compute/test/createComputeHyperdisk.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@

const path = require('path');
const assert = require('node:assert/strict');
const {before, after, describe, it} = require('mocha');
const {after, describe, it} = require('mocha');
const cp = require('child_process');
const {DisksClient} = require('@google-cloud/compute').v1;
const {getStaleDisks, deleteDisk} = require('./util');

const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
Expand All @@ -30,24 +29,13 @@ describe('Create compute hyperdisk', async () => {
const prefix = 'hyperdisk-name-941ad2d';
const diskName = `${prefix}${Math.floor(Math.random() * 1000 + 1)}`;
const zone = 'europe-central2-b';
const disksClient = new DisksClient();
let projectId;

before(async () => {
projectId = await disksClient.getProjectId();
after(async () => {
// Cleanup resources
Copy link
Contributor Author

@gryczj gryczj Oct 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this PR I also moved cleanup methods to after() to prevent keeping not used resources in our project after running the tests and to reduce the code.

const disks = await getStaleDisks(prefix);
await Promise.all(disks.map(disk => deleteDisk(disk.zone, disk.diskName)));
});

after(async () => {
await disksClient.delete({
project: projectId,
disk: diskName,
zone,
});
});

it('should create a new hyperdisk', () => {
const response = execSync(
`node ./disks/createComputeHyperdisk.js ${diskName} ${zone}`,
Expand Down
10 changes: 2 additions & 8 deletions compute/test/createComputeHyperdiskFromPool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

const path = require('path');
const assert = require('node:assert/strict');
const {after, before, describe, it} = require('mocha');
const {after, describe, it} = require('mocha');
const cp = require('child_process');
const {
getStaleDisks,
Expand All @@ -37,7 +37,7 @@ describe('Create compute hyperdisk from pool', async () => {
const storagePoolName = `${poolPrefix}${Math.floor(Math.random() * 1000 + 1)}5f`;
const zone = 'us-central1-a';

before(async () => {
after(async () => {
// Cleanup resources
const disks = await getStaleDisks(diskPrefix);
await Promise.all(disks.map(disk => deleteDisk(disk.zone, disk.diskName)));
Expand All @@ -49,12 +49,6 @@ describe('Create compute hyperdisk from pool', async () => {
);
});

after(async () => {
// Cleanup resources
await deleteDisk(zone, diskName);
await deleteStoragePool(zone, storagePoolName);
});

it('should create a new storage pool', async () => {
const response = execSync(
`node ./disks/createComputeHyperdiskPool.js ${storagePoolName} ${zone}`,
Expand Down
2 changes: 1 addition & 1 deletion compute/test/createInstanceTemplates.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

const compute = require('@google-cloud/compute');

const {describe, it} = require('mocha');
const {after, describe, it} = require('mocha');
const cp = require('child_process');
const {assert} = require('chai');

Expand Down
67 changes: 67 additions & 0 deletions compute/test/createInstanceToConsumeSharedReservation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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 {beforeEach, afterEach, describe, it} = require('mocha');
const assert = require('node:assert/strict');
const sinon = require('sinon');
const createInstanceToConsumeSharedReservation = require('../reservations/createInstanceToConsumeSharedReservation.js');

describe('Create instance to consume shared reservation', async () => {
const instanceName = 'instance-1';
let instancesClientMock;
let zoneOperationsClientMock;

beforeEach(() => {
instancesClientMock = {
insert: sinon.stub().resolves([
{
name: instanceName,
latestResponse: {
status: 'DONE',
name: 'operation-1234567890',
zone: {
value: 'us-central1-a',
},
},
},
]),
};
zoneOperationsClientMock = {
wait: sinon.stub().resolves([
{
latestResponse: {
status: 'DONE',
},
},
]),
};
});

afterEach(() => {
sinon.restore();
});

it('should create instance', async () => {
const response = await createInstanceToConsumeSharedReservation(
instancesClientMock,
zoneOperationsClientMock
);

assert(response.name.includes(instanceName));
});
});
Loading
Loading