Skip to content

Commit bd85f8f

Browse files
FrodoTheTrueAce Nassri
authored and
Ace Nassri
committed
chore(samples): create instance from template samples (#640)
1 parent dd5872a commit bd85f8f

File tree

3 files changed

+303
-12
lines changed

3 files changed

+303
-12
lines changed

compute/createInstanceFromTemplate.js

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* Creates a Compute Engine VM instance from an instance template.
17+
*
18+
* @param {string} projectId - ID or number of the project you want to use.
19+
* @param {string} zone - Name of the zone you want to check, for example: us-west3-b
20+
* @param {string} instanceName - Name of the new instance.
21+
* @param {string} instanceTemplateUrl - URL of the instance template using for creating the new instance. It can be a full or partial URL.
22+
* Examples:
23+
* - https://www.googleapis.com/compute/v1/projects/project/global/instanceTemplates/example-instance-template
24+
* - projects/project/global/instanceTemplates/example-instance-template
25+
* - global/instanceTemplates/example-instance-template
26+
*/
27+
function main(projectId, zone, instanceName, instanceTemplateUrl) {
28+
// [START compute_instances_create_from_template]
29+
/**
30+
* TODO(developer): Uncomment and replace these variables before running the sample.
31+
*/
32+
// const projectId = 'YOUR_PROJECT_ID';
33+
// const zone = 'europe-central2-b'
34+
// const instanceName = 'YOUR_INSTANCE_NAME'
35+
// const instanceTemplateUrl = 'YOUR_INSTANCE_TEMPLATE_URL'
36+
37+
const compute = require('@google-cloud/compute');
38+
39+
// Create a new instance from template in the specified project and zone.
40+
async function createInstanceFromTemplate() {
41+
const instancesClient = new compute.InstancesClient();
42+
43+
console.log(
44+
`Creating the ${instanceName} instance in ${zone} from template ${instanceTemplateUrl}...`
45+
);
46+
47+
const [response] = await instancesClient.insert({
48+
project: projectId,
49+
zone,
50+
instanceResource: {
51+
name: instanceName,
52+
},
53+
sourceInstanceTemplate: instanceTemplateUrl,
54+
});
55+
let operation = response.latestResponse;
56+
const operationsClient = new compute.ZoneOperationsClient();
57+
58+
// Wait for the create operation to complete.
59+
while (operation.status !== 'DONE') {
60+
[operation] = await operationsClient.wait({
61+
operation: operation.name,
62+
project: projectId,
63+
zone: operation.zone.split('/').pop(),
64+
});
65+
}
66+
67+
console.log('Instance created.');
68+
}
69+
70+
createInstanceFromTemplate();
71+
// [END compute_instances_create_from_template]
72+
}
73+
74+
main(...process.argv.slice(2));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* Creates a Compute Engine VM instance from an instance template, but overrides the disk and machine type options in the template.
17+
*
18+
* @param {string} projectId - ID or number of the project you want to use.
19+
* @param {string} zone - Name of the zone you want to check, for example: us-west3-b
20+
* @param {string} instanceName - Name of the new instance.
21+
* @param {string} instanceTemplateName - Name of the instance template to use when creating the new instance.
22+
* @param {string} machineType - Machine type you want to set in following format:
23+
* "zones/{zone}/machineTypes/{type_name}". For example:
24+
* "zones/europe-west3-c/machineTypes/f1-micro"
25+
* You can find the list of available machine types using:
26+
* https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list
27+
* @param {string} newDiskSourceImage - Path the the disk image you want to use for your new
28+
* disk. This can be one of the public images
29+
* (like "projects/debian-cloud/global/images/family/debian-10")
30+
* or a private image you have access to.
31+
* For a list of available public images, see the documentation:
32+
* http://cloud.google.com/compute/docs/images
33+
*/
34+
function main(
35+
projectId,
36+
zone,
37+
instanceName,
38+
instanceTemplateName,
39+
machineType = 'n1-standard-2',
40+
newDiskSourceImage = 'projects/debian-cloud/global/images/family/debian-10'
41+
) {
42+
// [START compute_instances_create_from_template_with_overrides]
43+
/**
44+
* TODO(developer): Uncomment and replace these variables before running the sample.
45+
*/
46+
// const projectId = 'YOUR_PROJECT_ID';
47+
// const zone = 'europe-central2-b';
48+
// const instanceName = 'YOUR_INSTANCE_NAME';
49+
// const instanceTemplateName = 'YOUR_INSTANCE_TEMPLATE_NAME';
50+
// const machineType = 'n1-standard-1';
51+
// const newDiskSourceImage = 'projects/debian-cloud/global/images/family/debian-10';
52+
53+
const compute = require('@google-cloud/compute');
54+
const computeProtos = compute.protos.google.cloud.compute.v1;
55+
56+
// Creates a new instance in the specified project and zone using a selected template, but overrides the disk and machine type options in the template.
57+
async function createInstanceFromTemplateWithOverrides() {
58+
const instancesClient = new compute.InstancesClient();
59+
const instanceTemplatesClient = new compute.InstanceTemplatesClient();
60+
61+
console.log(
62+
`Creating the ${instanceName} instance in ${zone} from template ${instanceTemplateName}...`
63+
);
64+
65+
// Retrieve an instance template by name.
66+
const [instanceTemplate] = await instanceTemplatesClient.get({
67+
project: projectId,
68+
instanceTemplate: instanceTemplateName,
69+
});
70+
71+
// Adjust diskType field of the instance template to use the URL formatting required by instances.insert.diskType
72+
// For instance template, there is only a name, not URL.
73+
for (const disk of instanceTemplate.properties.disks) {
74+
if (disk.initializeParams.diskType) {
75+
disk.initializeParams.diskType = `zones/${zone}/diskTypes/${disk.initializeParams.diskType}`;
76+
}
77+
}
78+
79+
const [response] = await instancesClient.insert({
80+
project: projectId,
81+
zone,
82+
instanceResource: {
83+
name: instanceName,
84+
machineType: `zones/${zone}/machineTypes/${machineType}`,
85+
disks: [
86+
// If you override a repeated field, all repeated values
87+
// for that property are replaced with the
88+
// corresponding values provided in the request.
89+
// When adding a new disk to existing disks,
90+
// insert all existing disks as well.
91+
...instanceTemplate.properties.disks,
92+
{
93+
initializeParams: {
94+
diskSizeGb: '10',
95+
sourceImage: newDiskSourceImage,
96+
},
97+
autoDelete: true,
98+
boot: false,
99+
type: computeProtos.AttachedDisk.Type.PERSISTENT,
100+
},
101+
],
102+
},
103+
sourceInstanceTemplate: instanceTemplate.selfLink,
104+
});
105+
let operation = response.latestResponse;
106+
const operationsClient = new compute.ZoneOperationsClient();
107+
108+
// Wait for the create operation to complete.
109+
while (operation.status !== 'DONE') {
110+
[operation] = await operationsClient.wait({
111+
operation: operation.name,
112+
project: projectId,
113+
zone: operation.zone.split('/').pop(),
114+
});
115+
}
116+
117+
console.log('Instance created.');
118+
}
119+
120+
createInstanceFromTemplateWithOverrides();
121+
// [END compute_instances_create_from_template_with_overrides]
122+
}
123+
124+
main(...process.argv.slice(2));

compute/test/samples.test.js

+105-12
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ const uuid = require('uuid');
2323
const cp = require('child_process');
2424
const {assert} = require('chai');
2525

26-
const instancesClient = new compute.InstancesClient({fallback: 'rest'});
27-
const projectsClient = new compute.ProjectsClient({fallback: 'rest'});
28-
const firewallsClient = new compute.FirewallsClient({fallback: 'rest'});
26+
const instancesClient = new compute.InstancesClient();
27+
const projectsClient = new compute.ProjectsClient();
28+
const firewallsClient = new compute.FirewallsClient();
29+
const instanceTemplatesClient = new compute.InstanceTemplatesClient();
2930

3031
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
3132

@@ -43,6 +44,15 @@ const delay = async test => {
4344
});
4445
};
4546

47+
const getInstance = async (projectId, zone, instanceName) => {
48+
const [instance] = await instancesClient.get({
49+
project: projectId,
50+
zone,
51+
instance: instanceName,
52+
});
53+
return instance;
54+
};
55+
4656
describe('samples', () => {
4757
const instanceName = `gcloud-test-intance-${uuid.v4().split('-')[0]}`;
4858
const zone = 'europe-central2-b';
@@ -197,15 +207,6 @@ describe('samples', () => {
197207
});
198208
});
199209

200-
const getInstance = async (projectId, zone, instanceName) => {
201-
const [instance] = await instancesClient.get({
202-
project: projectId,
203-
zone,
204-
instance: instanceName,
205-
});
206-
return instance;
207-
};
208-
209210
describe('start/stop instances', () => {
210211
it('should start/stop instances', async () => {
211212
const projectId = await instancesClient.getProjectId();
@@ -378,4 +379,96 @@ describe('samples', () => {
378379
);
379380
});
380381
});
382+
383+
describe('instance template', () => {
384+
const instanceTemplateName = `instance-template-${uuid.v4().split('-')[0]}`;
385+
const zone = 'europe-central2-b';
386+
387+
before(async () => {
388+
const projectId = await instancesClient.getProjectId();
389+
const [response] = await instanceTemplatesClient.insert({
390+
project: projectId,
391+
instanceTemplateResource: {
392+
name: instanceTemplateName,
393+
properties: {
394+
machineType: 'n1-standard-1',
395+
disks: [
396+
{
397+
initializeParams: {
398+
diskSizeGb: '10',
399+
sourceImage:
400+
'projects/debian-cloud/global/images/family/debian-10',
401+
},
402+
autoDelete: true,
403+
boot: true,
404+
type: computeProtos.AttachedDisk.Type.PERSISTENT,
405+
},
406+
],
407+
networkInterfaces: [
408+
{
409+
name: 'global/networks/default',
410+
},
411+
],
412+
},
413+
},
414+
});
415+
416+
let operation = response.latestResponse;
417+
const operationsClient = new compute.GlobalOperationsClient();
418+
419+
// Wait for the create operation to complete.
420+
while (operation.status !== 'DONE') {
421+
[operation] = await operationsClient.wait({
422+
operation: operation.name,
423+
project: projectId,
424+
});
425+
}
426+
});
427+
428+
after(async () => {
429+
const projectId = await instancesClient.getProjectId();
430+
const [response] = await instanceTemplatesClient.delete({
431+
project: projectId,
432+
instanceTemplate: instanceTemplateName,
433+
});
434+
435+
let operation = response.latestResponse;
436+
const operationsClient = new compute.GlobalOperationsClient();
437+
438+
// Wait for the create operation to complete.
439+
while (operation.status !== 'DONE') {
440+
[operation] = await operationsClient.wait({
441+
operation: operation.name,
442+
project: projectId,
443+
});
444+
}
445+
});
446+
447+
it('should create instance from template', async () => {
448+
const projectId = await instancesClient.getProjectId();
449+
const instanceName = `instance-${uuid.v4().split('-')[0]}`;
450+
451+
const output = execSync(
452+
`node createInstanceFromTemplate ${projectId} ${zone} ${instanceName} global/instanceTemplates/${instanceTemplateName}`
453+
);
454+
assert.include(output, 'Instance created.');
455+
456+
execSync(`node deleteInstance ${projectId} ${zone} ${instanceName}`);
457+
});
458+
459+
it('should create instance from template with overrides', async () => {
460+
const projectId = await instancesClient.getProjectId();
461+
const instanceName = `instance-${uuid.v4().split('-')[0]}`;
462+
463+
const output = execSync(
464+
`node createInstanceFromTemplateWithOverrides ${projectId} ${zone} ${instanceName} ${instanceTemplateName}`
465+
);
466+
assert.include(output, 'Instance created.');
467+
468+
const instance = await getInstance(projectId, zone, instanceName);
469+
assert.equal(instance.disks.length, 2);
470+
471+
execSync(`node deleteInstance ${projectId} ${zone} ${instanceName}`);
472+
});
473+
});
381474
});

0 commit comments

Comments
 (0)