From 65382ce4191343f0bae00f2b9dc30496534f1b99 Mon Sep 17 00:00:00 2001 From: Fedor Isakov Date: Tue, 22 Mar 2022 23:00:37 +0100 Subject: [PATCH] chore(samples): add creating managing windows instances samples (#704) --- .../createWindowsServerInstanceExternalIP.js | 114 ++++++++++++++++ .../createWindowsServerInstanceInternalIP.js | 124 ++++++++++++++++++ compute/test/creatingManagingWindows.test.js | 120 +++++++++++++++++ 3 files changed, 358 insertions(+) create mode 100644 compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceExternalIP.js create mode 100644 compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceInternalIP.js create mode 100644 compute/test/creatingManagingWindows.test.js diff --git a/compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceExternalIP.js b/compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceExternalIP.js new file mode 100644 index 0000000000..052e667633 --- /dev/null +++ b/compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceExternalIP.js @@ -0,0 +1,114 @@ +// Copyright 2022 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. + +/** + * Creates a new Windows Server instance that has an external IP address. + * + * @param {string} projectId - ID or number of the project you want to use. + * @param {string} zone - Name of the zone you want to use, for example: us-west3-b + * @param {string} instanceName - Name of the new machine. + * @param {string} machineType - Machine type you want to create in following format: + * "zones/{zone}/machineTypes/{type_name}". For example: + * "zones/europe-west3-c/machineTypes/f1-micro" + * You can find the list of available machine types using: + * https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list + * @param {string} sourceImageFamily - Name of the public image family for Windows Server or SQL Server images. + * https://cloud.google.com/compute/docs/images#os-compute-support + */ +function main( + projectId, + zone, + instanceName, + machineType = 'n1-standard-1', + sourceImageFamily = 'windows-2012-r2' +) { + // [START compute_create_windows_instance_external_ip] + /** + * 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 machineType = 'n1-standard-1'; + // const sourceImageFamily = 'windows-2012-r2'; + + const compute = require('@google-cloud/compute'); + + async function createWndowsServerInstanceExpernalIP() { + const instancesClient = new compute.InstancesClient(); + + const [response] = await instancesClient.insert({ + instanceResource: { + name: instanceName, + disks: [ + { + // Describe the size and source image of the boot disk to attach to the instance. + initializeParams: { + diskSizeGb: '64', + sourceImage: `projects/windows-cloud/global/images/family/${sourceImageFamily}/`, + }, + autoDelete: true, + boot: true, + type: 'PERSISTENT', + }, + ], + machineType: `zones/${zone}/machineTypes/${machineType}`, + networkInterfaces: [ + { + accessConfigs: [ + { + type: 'ONE_TO_ONE_NAT', + name: 'External NAT', + }, + ], + // If you going you use custom VPC network, it must be configured to allow access to kms.windows.googlecloud.com. + // https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server. + name: 'global/networks/default', + }, + ], + // If you chose an image that supports Shielded VM, you can optionally change the instance's Shielded VM settings. + // "shieldedInstanceConfig": { + // "enableSecureBoot": true, + // "enableVtpm": true, + // "enableIntegrityMonitoring": true + // }, + }, + project: projectId, + zone, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the create operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log('Instance created.'); + } + + createWndowsServerInstanceExpernalIP(); + // [END compute_create_windows_instance_external_ip] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceInternalIP.js b/compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceInternalIP.js new file mode 100644 index 0000000000..fc6614fd0a --- /dev/null +++ b/compute/instances/windows/creating-managing-windows-instances/createWindowsServerInstanceInternalIP.js @@ -0,0 +1,124 @@ +// Copyright 2022 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. + +/** + * Creates a new Windows Server instance that has only an internal IP address. + * + * @param {string} projectId - ID or number of the project you want to use. + * @param {string} zone - Name of the zone you want to use, for example: us-west3-b + * @param {string} instanceName - Name of the new machine. + * @param {string} machineType - Machine type you want to create in following format: + * "zones/{zone}/machineTypes/{type_name}". For example: + * "zones/europe-west3-c/machineTypes/f1-micro" + * You can find the list of available machine types using: + * https://cloud.google.com/sdk/gcloud/reference/compute/machine-types/list + * @param {string} sourceImageFamily - Name of the public image family for Windows Server or SQL Server images. + * https://cloud.google.com/compute/docs/images#os-compute-support + * @param {string} networkLink - Name of the network you want the new instance to use. + * For example: "global/networks/default" represents the network + * named "default", which is created automatically for each project. + * @param {string} subnetworkLink - Name of the subnetwork you want the new instance to use. + * This value uses the following format: + * "regions/{region}/subnetworks/{subnetwork_name}" + */ +function main( + projectId, + zone, + instanceName, + machineType = 'n1-standard-1', + sourceImageFamily = 'windows-2012-r2', + networkLink = 'global/networks/default', + subnetworkLink = 'regions/europe-central2/subnetworks/default' +) { + // [START compute_create_windows_instance_internal_ip] + /** + * 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 machineType = 'n1-standard-1'; + // const sourceImageFamily = 'windows-2012-r2'; + // const networkLink = 'global/networks/default'; + // const subnetworkLink = 'regions/europe-central2/subnetworks/default'; + + const compute = require('@google-cloud/compute'); + + async function createWndowsServerInstanceExpernalIP() { + const instancesClient = new compute.InstancesClient(); + + const [response] = await instancesClient.insert({ + instanceResource: { + name: instanceName, + disks: [ + { + // Describe the size and source image of the boot disk to attach to the instance. + initializeParams: { + diskSizeGb: '64', + sourceImage: `projects/windows-cloud/global/images/family/${sourceImageFamily}/`, + }, + autoDelete: true, + boot: true, + type: 'PERSISTENT', + }, + ], + machineType: `zones/${zone}/machineTypes/${machineType}`, + networkInterfaces: [ + { + // You must verify or configure routes and firewall rules in your VPC network + // to allow access to kms.windows.googlecloud.com. + // More information about access to kms.windows.googlecloud.com: https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#kms-server + + // Additionally, you must enable Private Google Access for subnets in your VPC network + // that contain Windows instances with only internal IP addresses. + // More information about Private Google Access: https://cloud.google.com/vpc/docs/configure-private-google-access#enabling + name: networkLink, + subnetwork: subnetworkLink, + }, + ], + // If you chose an image that supports Shielded VM, you can optionally change the instance's Shielded VM settings. + // "shieldedInstanceConfig": { + // "enableSecureBoot": true, + // "enableVtpm": true, + // "enableIntegrityMonitoring": true + // }, + }, + project: projectId, + zone, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the create operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log('Instance created.'); + } + + createWndowsServerInstanceExpernalIP(); + // [END compute_create_windows_instance_internal_ip] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/compute/test/creatingManagingWindows.test.js b/compute/test/creatingManagingWindows.test.js new file mode 100644 index 0000000000..50b219b9b2 --- /dev/null +++ b/compute/test/creatingManagingWindows.test.js @@ -0,0 +1,120 @@ +// Copyright 2022 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. + +'use strict'; + +const compute = require('@google-cloud/compute'); + +const {describe, it} = require('mocha'); +const cp = require('child_process'); +const {assert} = require('chai'); + +const {generateTestId, getStaleVMInstances, deleteInstance} = require('./util'); + +const instancesClient = new compute.InstancesClient(); +const firewallsClient = new compute.FirewallsClient(); +const routesClient = new compute.RoutesClient(); +const globalOperationsClient = new compute.GlobalOperationsClient(); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const deleteFirewallRule = async (projectId, firewallRule) => { + const [response] = await firewallsClient.delete({ + project: projectId, + firewall: firewallRule, + }); + let operation = response.latestResponse; + + // Wait for the delete operation to complete. + while (operation.status !== 'DONE') { + [operation] = await globalOperationsClient.wait({ + operation: operation.name, + project: projectId, + }); + } +}; + +const deleteRoute = async (projectId, routeName) => { + const [response] = await routesClient.delete({ + project: projectId, + route: routeName, + }); + let operation = response.latestResponse; + const operationsClient = new compute.GlobalOperationsClient(); + + // Wait for the delete operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + }); + } +}; + +describe('creating managing windows instances tests', () => { + const instanceName = generateTestId(); + const firewallRuleName = generateTestId(); + const networkName = 'global/networks/default-compute'; + const subnetworkName = 'regions/europe-central2/subnetworks/default-compute'; + const routeName = generateTestId(); + const zone = 'europe-central2-b'; + const machineType = 'n1-standard-1'; + const sourceImageFamily = 'windows-2012-r2'; + + before(async () => { + const instances = await getStaleVMInstances(); + await Promise.all( + instances.map(instance => + deleteInstance(instance.zone, instance.instanceName) + ) + ); + }); + + it('should create windows server instance with external IP', async () => { + const projectId = await instancesClient.getProjectId(); + + const output = execSync( + `node instances/windows/creating-managing-windows-instances/createWindowsServerInstanceExternalIP ${projectId} ${zone} ${instanceName}` + ); + assert.match(output, /Instance created./); + + execSync(`node deleteInstance ${projectId} ${zone} ${instanceName}`); + }); + + it('should create windows server instance with internal IP and firewall rule', async () => { + const projectId = await instancesClient.getProjectId(); + + const output = execSync( + `node instances/windows/creating-managing-windows-instances/createWindowsServerInstanceInternalIP ${projectId} ${zone} ${instanceName} ${machineType} ${sourceImageFamily} ${networkName} ${subnetworkName}` + ); + + assert.match(output, /Instance created./); + + const outputFirewall = execSync( + `node instances/windows/creating-managing-windows-instances/createFirewallRuleForWindowsActivationHost ${projectId} ${firewallRuleName} ${networkName}` + ); + + assert.match(outputFirewall, /Firewall rule created./); + + const outputRoute = execSync( + `node instances/windows/creating-managing-windows-instances/createRouteToWindowsActivationHost ${projectId} ${routeName} ${networkName}` + ); + + assert.match(outputRoute, /Route created./); + + await deleteRoute(projectId, routeName); + await deleteFirewallRule(projectId, firewallRuleName); + execSync(`node deleteInstance ${projectId} ${zone} ${instanceName}`); + }); +});