From 69e0724fe51d241d6b63734afb472497b79243da Mon Sep 17 00:00:00 2001 From: Joanna Grycz Date: Tue, 5 Nov 2024 12:45:05 +0100 Subject: [PATCH 1/4] feat: compute_disk_create_secondary --- compute/disks/createSecondaryDisk.js | 104 +++++++++++++++++++++++ compute/test/createSecondaryDisk.test.js | 87 +++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 compute/disks/createSecondaryDisk.js create mode 100644 compute/test/createSecondaryDisk.test.js diff --git a/compute/disks/createSecondaryDisk.js b/compute/disks/createSecondaryDisk.js new file mode 100644 index 0000000000..78a6a9aec4 --- /dev/null +++ b/compute/disks/createSecondaryDisk.js @@ -0,0 +1,104 @@ +/* + * 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( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_create_secondary] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project for the secondary disk. + const secondaryProjectId = await disksClient.getProjectId(); + + // The zone for the secondary disk. The primary and secondary disks must be in different regions. + // secondaryLocation = 'europe-west4-a'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project that contains the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone for the primary disk. + // primaryLocation = 'europe-central2-b'; + + // The name of the primary disk that the secondary disk receives data from. + // primaryDiskName = 'primary-disk-name'; + + // The disk type. Must be one of `pd-ssd` or `pd-balanced`. + const diskType = `zones/${secondaryLocation}/diskTypes/pd-balanced`; + + // The size of the secondary disk in gigabytes. + const diskSizeGb = 10; + + // Create a secondary disk identical to the primary disk. + async function callCreateComputeSecondaryDisk() { + // Create a secondary disk + const disk = new compute.Disk({ + sizeGb: diskSizeGb, + name: secondaryDiskName, + zone: secondaryLocation, + type: diskType, + asyncPrimaryDisk: new compute.DiskAsyncReplication({ + // Make sure that the primary disk supports asynchronous replication. + // Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible. + disk: `projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`, + }), + }); + + const [response] = await disksClient.insert({ + project: secondaryProjectId, + zone: secondaryLocation, + diskResource: disk, + }); + + let operation = response.latestResponse; + + // Wait for the create secondary disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Secondary disk: ${secondaryDiskName} created.`); + } + + await callCreateComputeSecondaryDisk(); + // [END compute_disk_create_secondary] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/test/createSecondaryDisk.test.js b/compute/test/createSecondaryDisk.test.js new file mode 100644 index 0000000000..94bc687139 --- /dev/null +++ b/compute/test/createSecondaryDisk.test.js @@ -0,0 +1,87 @@ +/* + * 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 path = require('path'); +const assert = require('node:assert/strict'); +const uuid = require('uuid'); +const {before, after, describe, it} = require('mocha'); +const cp = require('child_process'); +const computeLib = require('@google-cloud/compute'); +const {getStaleDisks, deleteDisk} = require('./util'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +async function createDisk(diskName, zone) { + const disksClient = new computeLib.DisksClient(); + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + const projectId = await disksClient.getProjectId(); + + const [response] = await disksClient.insert({ + project: projectId, + zone, + diskResource: { + sizeGb: 10, + name: diskName, + zone, + type: `zones/${zone}/diskTypes/pd-balanced`, + }, + }); + + let operation = response.latestResponse; + + // Wait for the create disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Disk: ${diskName} created.`); +} + +describe('Create compute secondary disk', async () => { + const prefix = 'compute-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryZone = 'europe-west4-a'; + const primaryZone = 'europe-central2-b'; + + before(async () => { + await createDisk(primaryDiskName, primaryZone); + }); + + after(async () => { + // Cleanup resources + const disks = await getStaleDisks(prefix); + await Promise.all(disks.map(disk => deleteDisk(disk.zone, disk.diskName))); + }); + + it('should create a zonal secondary disk', () => { + const response = execSync( + `node ./disks/createSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert(response.includes(`Secondary disk: ${secondaryDiskName} created.`)); + }); +}); From f3058710980fad60d9bb79551281a25d0446e79e Mon Sep 17 00:00:00 2001 From: Joanna Grycz Date: Tue, 5 Nov 2024 13:46:39 +0100 Subject: [PATCH 2/4] feat: compute_disk_create_secondary_regional --- compute/disks/createRegionalSecondaryDisk.js | 108 ++++++++++++++++ ...aryDisk.js => createZonalSecondaryDisk.js} | 0 .../test/createRegionalSecondaryDisk.test.js | 119 ++++++++++++++++++ ...st.js => createZonalSecondaryDisk.test.js} | 12 +- 4 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 compute/disks/createRegionalSecondaryDisk.js rename compute/disks/{createSecondaryDisk.js => createZonalSecondaryDisk.js} (100%) create mode 100644 compute/test/createRegionalSecondaryDisk.test.js rename compute/test/{createSecondaryDisk.test.js => createZonalSecondaryDisk.test.js} (86%) diff --git a/compute/disks/createRegionalSecondaryDisk.js b/compute/disks/createRegionalSecondaryDisk.js new file mode 100644 index 0000000000..f9063ef2d7 --- /dev/null +++ b/compute/disks/createRegionalSecondaryDisk.js @@ -0,0 +1,108 @@ +/* + * 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( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_create_secondary_regional] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a regionDisksClient + const regionDisksClient = new computeLib.RegionDisksClient(); + // Instantiate a regionOperationsClient + const regionOperationsClient = new computeLib.RegionOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project for the secondary disk. + const secondaryProjectId = await regionDisksClient.getProjectId(); + + // The region for the secondary disk. + // secondaryLocation = 'europe-west4'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project that contains the primary disk. + const primaryProjectId = await regionDisksClient.getProjectId(); + + // The region for the primary disk. + // primaryLocation = 'europe-central2'; + + // The name of the primary disk that the secondary disk receives data from. + // primaryDiskName = 'primary-disk-name'; + + // The disk type. Must be one of `pd-ssd` or `pd-balanced`. + const diskType = `regions/${secondaryLocation}/diskTypes/pd-balanced`; + + // The size of the secondary disk in gigabytes. + const diskSizeGb = 10; + + // Create a secondary disk identical to the primary disk. + async function callCreateComputeRegionalSecondaryDisk() { + // Create a secondary disk + const disk = new compute.Disk({ + sizeGb: diskSizeGb, + name: secondaryDiskName, + region: secondaryLocation, + type: diskType, + replicaZones: [ + `zones/${secondaryLocation}-a`, + `zones/${secondaryLocation}-b`, + ], + asyncPrimaryDisk: new compute.DiskAsyncReplication({ + // Make sure that the primary disk supports asynchronous replication. + // Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible. + disk: `projects/${primaryProjectId}/regions/${primaryLocation}/disks/${primaryDiskName}`, + }), + }); + + const [response] = await regionDisksClient.insert({ + project: secondaryProjectId, + diskResource: disk, + region: secondaryLocation, + }); + + let operation = response.latestResponse; + + // Wait for the create secondary disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await regionOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + region: secondaryLocation, + }); + } + + console.log(`Secondary disk: ${secondaryDiskName} created.`); + } + + await callCreateComputeRegionalSecondaryDisk(); + // [END compute_disk_create_secondary_regional] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/disks/createSecondaryDisk.js b/compute/disks/createZonalSecondaryDisk.js similarity index 100% rename from compute/disks/createSecondaryDisk.js rename to compute/disks/createZonalSecondaryDisk.js diff --git a/compute/test/createRegionalSecondaryDisk.test.js b/compute/test/createRegionalSecondaryDisk.test.js new file mode 100644 index 0000000000..2a3dde96bd --- /dev/null +++ b/compute/test/createRegionalSecondaryDisk.test.js @@ -0,0 +1,119 @@ +/* + * 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 path = require('path'); +const assert = require('node:assert/strict'); +const uuid = require('uuid'); +const {before, after, describe, it} = require('mocha'); +const cp = require('child_process'); +const computeLib = require('@google-cloud/compute'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +const disksClient = new computeLib.RegionDisksClient(); +const regionOperationsClient = new computeLib.RegionOperationsClient(); + +async function createDisk(diskName, region) { + const projectId = await disksClient.getProjectId(); + const [response] = await disksClient.insert({ + project: projectId, + region, + diskResource: { + sizeGb: 10, + name: diskName, + region, + type: `regions/${region}/diskTypes/pd-balanced`, + replicaZones: [`zones/${region}-a`, `zones/${region}-b`], + }, + }); + + let operation = response.latestResponse; + + // Wait for the create disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await regionOperationsClient.wait({ + operation: operation.name, + project: projectId, + region, + }); + } + + console.log(`Disk: ${diskName} created.`); +} + +async function deleteDisk(region, diskName) { + const projectId = await disksClient.getProjectId(); + const [response] = await disksClient.delete({ + project: projectId, + disk: diskName, + region, + }); + let operation = response.latestResponse; + + console.log(`Deleting ${diskName}`); + + // Wait for the delete operation to complete. + while (operation.status !== 'DONE') { + [operation] = await regionOperationsClient.wait({ + operation: operation.name, + project: projectId, + region, + }); + } +} + +describe('Create compute regional secondary disk', async () => { + const prefix = 'regional-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryRegion = 'europe-west4'; + const primaryRegion = 'europe-central2'; + const disks = [ + { + diskName: secondaryDiskName, + region: secondaryRegion, + }, + { + diskName: primaryDiskName, + region: primaryRegion, + }, + ]; + + before(async () => { + await createDisk(primaryDiskName, primaryRegion); + }); + + after(async () => { + // Cleanup resources + await Promise.all( + disks.map(disk => deleteDisk(disk.region, disk.diskName)) + ); + }); + + it('should create a regional secondary disk', () => { + const response = execSync( + `node ./disks/createRegionalSecondaryDisk.js ${secondaryDiskName} ${secondaryRegion} ${primaryDiskName} ${primaryRegion}`, + { + cwd, + } + ); + + assert(response.includes(`Secondary disk: ${secondaryDiskName} created.`)); + }); +}); diff --git a/compute/test/createSecondaryDisk.test.js b/compute/test/createZonalSecondaryDisk.test.js similarity index 86% rename from compute/test/createSecondaryDisk.test.js rename to compute/test/createZonalSecondaryDisk.test.js index 94bc687139..860f3ce299 100644 --- a/compute/test/createSecondaryDisk.test.js +++ b/compute/test/createZonalSecondaryDisk.test.js @@ -57,12 +57,14 @@ async function createDisk(diskName, zone) { console.log(`Disk: ${diskName} created.`); } -describe('Create compute secondary disk', async () => { - const prefix = 'compute-disk'; +describe('Create compute zonal secondary disk', async () => { + const prefix = 'zonal-disk'; const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; - const secondaryZone = 'europe-west4-a'; - const primaryZone = 'europe-central2-b'; + const secondaryRegion = 'europe-west4'; + const primaryRegion = 'europe-central2'; + const secondaryZone = `${secondaryRegion}-a`; + const primaryZone = `${primaryRegion}-a`; before(async () => { await createDisk(primaryDiskName, primaryZone); @@ -76,7 +78,7 @@ describe('Create compute secondary disk', async () => { it('should create a zonal secondary disk', () => { const response = execSync( - `node ./disks/createSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + `node ./disks/createZonalSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, { cwd, } From a250786b281842fc4e25e50e26a4fed3c493ef75 Mon Sep 17 00:00:00 2001 From: Joanna Grycz Date: Wed, 6 Nov 2024 11:47:13 +0100 Subject: [PATCH 3/4] feat: compute_disk_create_secondary_custom --- compute/disks/createCustomSecondaryDisk.js | 118 ++++++++++++++++++ .../test/createCustomSecondaryDisk.test.js | 103 +++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 compute/disks/createCustomSecondaryDisk.js create mode 100644 compute/test/createCustomSecondaryDisk.test.js diff --git a/compute/disks/createCustomSecondaryDisk.js b/compute/disks/createCustomSecondaryDisk.js new file mode 100644 index 0000000000..223ef9429d --- /dev/null +++ b/compute/disks/createCustomSecondaryDisk.js @@ -0,0 +1,118 @@ +/* + * 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( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_create_secondary_custom] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project for the secondary disk. + const secondaryProjectId = await disksClient.getProjectId(); + + // The zone for the secondary disk. The primary and secondary disks must be in different regions. + // secondaryLocation = 'europe-west4-a'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project that contains the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone for the primary disk. + // primaryLocation = 'europe-central2-b'; + + // The name of the primary disk that the secondary disk receives data from. + // primaryDiskName = 'primary-disk-name'; + + // The disk type. Must be one of `pd-ssd` or `pd-balanced`. + const diskType = `zones/${secondaryLocation}/diskTypes/pd-balanced`; + + // The size of the secondary disk in gigabytes. + const diskSizeGb = 10; + + // Create a secondary disk identical to the primary disk. + async function callCreateComputeSecondaryDisk() { + // Create a secondary disk + const disk = new compute.Disk({ + sizeGb: diskSizeGb, + name: secondaryDiskName, + zone: secondaryLocation, + type: diskType, + asyncPrimaryDisk: new compute.DiskAsyncReplication({ + // Make sure that the primary disk supports asynchronous replication. + // Only certain persistent disk types, like `pd-balanced` and `pd-ssd`, are eligible. + disk: `projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`, + }), + // Specify additional guest OS features. + // You don't need to include the guest OS features of the primary disk. + // The secondary disk automatically inherits the guest OS features of the primary disk. + guestOsFeatures: [ + new compute.GuestOsFeature({ + type: 'NEW_FEATURE_ID_1', + }), + ], + // Assign additional labels to the secondary disk. + // You don't need to include the labels of the primary disk. + // The secondary disk automatically inherits the labels from the primary disk + labels: { + key: 'value', + }, + }); + + const [response] = await disksClient.insert({ + project: secondaryProjectId, + zone: secondaryLocation, + diskResource: disk, + }); + + let operation = response.latestResponse; + + // Wait for the create secondary disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Custom secondary disk: ${secondaryDiskName} created.`); + } + + await callCreateComputeSecondaryDisk(); + // [END compute_disk_create_secondary_custom] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/test/createCustomSecondaryDisk.test.js b/compute/test/createCustomSecondaryDisk.test.js new file mode 100644 index 0000000000..d0429192fc --- /dev/null +++ b/compute/test/createCustomSecondaryDisk.test.js @@ -0,0 +1,103 @@ +/* + * 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 path = require('path'); +const assert = require('node:assert/strict'); +const uuid = require('uuid'); +const {before, after, describe, it} = require('mocha'); +const cp = require('child_process'); +const computeLib = require('@google-cloud/compute'); +const {getStaleDisks, deleteDisk} = require('./util'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +const disksClient = new computeLib.DisksClient(); +const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + +async function createDisk(diskName, zone, projectId) { + const [response] = await disksClient.insert({ + project: projectId, + zone, + diskResource: { + sizeGb: 10, + name: diskName, + zone, + type: `zones/${zone}/diskTypes/pd-balanced`, + }, + }); + + let operation = response.latestResponse; + + // Wait for the create disk operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Disk: ${diskName} created.`); +} + +describe('Create compute custom secondary disk', async () => { + const prefix = 'custom-disk'; + const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; + const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; + const secondaryRegion = 'europe-west4'; + const primaryRegion = 'europe-central2'; + const secondaryZone = `${secondaryRegion}-a`; + const primaryZone = `${primaryRegion}-a`; + let projectId; + + before(async () => { + projectId = await disksClient.getProjectId(); + await createDisk(primaryDiskName, primaryZone, projectId); + }); + + after(async () => { + // Cleanup resources + const disks = await getStaleDisks(prefix); + await Promise.all(disks.map(disk => deleteDisk(disk.zone, disk.diskName))); + }); + + it('should create a custom secondary disk', async () => { + const expectedProperties = { + guestOsFeatures: [{type: 'FEATURE_TYPE_UNSPECIFIED', _type: 'type'}], + labels: { + key: 'value', + }, + }; + execSync( + `node ./disks/createCustomSecondaryDisk.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + const [disk] = await disksClient.get({ + project: projectId, + zone: secondaryZone, + disk: secondaryDiskName, + }); + + assert.deepEqual(disk.guestOsFeatures, expectedProperties.guestOsFeatures); + assert.deepEqual(disk.labels, expectedProperties.labels); + }); +}); From ded92eed3bb8a9e46ccffb56ef399bc584982dea Mon Sep 17 00:00:00 2001 From: Joanna Grycz Date: Wed, 6 Nov 2024 15:52:34 +0100 Subject: [PATCH 4/4] feat: compute_disk_start/stop_replication --- compute/disks/createCustomSecondaryDisk.js | 15 ++- compute/disks/createRegionalSecondaryDisk.js | 4 +- compute/disks/createZonalSecondaryDisk.js | 4 +- compute/disks/startReplication.js | 91 +++++++++++++++++++ compute/disks/stopReplication.js | 70 ++++++++++++++ ...isk.test.js => zonalSecondaryDisk.test.js} | 32 ++++++- 6 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 compute/disks/startReplication.js create mode 100644 compute/disks/stopReplication.js rename compute/test/{createZonalSecondaryDisk.test.js => zonalSecondaryDisk.test.js} (78%) diff --git a/compute/disks/createCustomSecondaryDisk.js b/compute/disks/createCustomSecondaryDisk.js index 223ef9429d..db24e59d8b 100644 --- a/compute/disks/createCustomSecondaryDisk.js +++ b/compute/disks/createCustomSecondaryDisk.js @@ -27,6 +27,7 @@ async function main( const computeLib = require('@google-cloud/compute'); const compute = computeLib.protos.google.cloud.compute.v1; + // If you want to create regional disk, you should use: RegionDisksClient and RegionOperationsClient. // Instantiate a diskClient const disksClient = new computeLib.DisksClient(); // Instantiate a zoneOperationsClient @@ -38,8 +39,9 @@ async function main( // The project for the secondary disk. const secondaryProjectId = await disksClient.getProjectId(); - // The zone for the secondary disk. The primary and secondary disks must be in different regions. - // secondaryLocation = 'europe-west4-a'; + // The zone or region for the secondary disk. The primary and secondary disks must be in different regions. + // If you use RegionDisksClient- define region, if DisksClient- define zone. + // secondaryLocation = 'us-central1-a'; // The name of the secondary disk. // secondaryDiskName = 'secondary-disk-name'; @@ -47,8 +49,9 @@ async function main( // The project that contains the primary disk. const primaryProjectId = await disksClient.getProjectId(); - // The zone for the primary disk. - // primaryLocation = 'europe-central2-b'; + // The zone or region for the primary disk. + // If you use RegionDisksClient- define region, if DisksClient- define zone. + // primaryLocation = 'us-central1-b'; // The name of the primary disk that the secondary disk receives data from. // primaryDiskName = 'primary-disk-name'; @@ -65,6 +68,7 @@ async function main( const disk = new compute.Disk({ sizeGb: diskSizeGb, name: secondaryDiskName, + // If you use RegionDisksClient, pass region as an argument instead of zone zone: secondaryLocation, type: diskType, asyncPrimaryDisk: new compute.DiskAsyncReplication({ @@ -73,6 +77,7 @@ async function main( disk: `projects/${primaryProjectId}/zones/${primaryLocation}/disks/${primaryDiskName}`, }), // Specify additional guest OS features. + // To learn more about OS features, open: `https://cloud.google.com/compute/docs/disks/async-pd/configure?authuser=0#secondary2`. // You don't need to include the guest OS features of the primary disk. // The secondary disk automatically inherits the guest OS features of the primary disk. guestOsFeatures: [ @@ -90,6 +95,7 @@ async function main( const [response] = await disksClient.insert({ project: secondaryProjectId, + // If you use RegionDisksClient, pass region as an argument instead of zone zone: secondaryLocation, diskResource: disk, }); @@ -101,6 +107,7 @@ async function main( [operation] = await zoneOperationsClient.wait({ operation: operation.name, project: secondaryProjectId, + // If you use RegionOperationsClient, pass region as an argument instead of zone zone: operation.zone.split('/').pop(), }); } diff --git a/compute/disks/createRegionalSecondaryDisk.js b/compute/disks/createRegionalSecondaryDisk.js index f9063ef2d7..aa7d9948bc 100644 --- a/compute/disks/createRegionalSecondaryDisk.js +++ b/compute/disks/createRegionalSecondaryDisk.js @@ -39,7 +39,7 @@ async function main( const secondaryProjectId = await regionDisksClient.getProjectId(); // The region for the secondary disk. - // secondaryLocation = 'europe-west4'; + // secondaryLocation = 'us-central1'; // The name of the secondary disk. // secondaryDiskName = 'secondary-disk-name'; @@ -48,7 +48,7 @@ async function main( const primaryProjectId = await regionDisksClient.getProjectId(); // The region for the primary disk. - // primaryLocation = 'europe-central2'; + // primaryLocation = 'us-central2'; // The name of the primary disk that the secondary disk receives data from. // primaryDiskName = 'primary-disk-name'; diff --git a/compute/disks/createZonalSecondaryDisk.js b/compute/disks/createZonalSecondaryDisk.js index 78a6a9aec4..08ab048433 100644 --- a/compute/disks/createZonalSecondaryDisk.js +++ b/compute/disks/createZonalSecondaryDisk.js @@ -39,7 +39,7 @@ async function main( const secondaryProjectId = await disksClient.getProjectId(); // The zone for the secondary disk. The primary and secondary disks must be in different regions. - // secondaryLocation = 'europe-west4-a'; + // secondaryLocation = 'us-central1-a'; // The name of the secondary disk. // secondaryDiskName = 'secondary-disk-name'; @@ -48,7 +48,7 @@ async function main( const primaryProjectId = await disksClient.getProjectId(); // The zone for the primary disk. - // primaryLocation = 'europe-central2-b'; + // primaryLocation = 'us-central1-b'; // The name of the primary disk that the secondary disk receives data from. // primaryDiskName = 'primary-disk-name'; diff --git a/compute/disks/startReplication.js b/compute/disks/startReplication.js new file mode 100644 index 0000000000..606fb33824 --- /dev/null +++ b/compute/disks/startReplication.js @@ -0,0 +1,91 @@ +/* + * 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( + secondaryDiskName, + secondaryLocation, + primaryDiskName, + primaryLocation +) { + // [START compute_disk_start_replication] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + const compute = computeLib.protos.google.cloud.compute.v1; + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project of the secondary disk. + const secondaryProjectId = await disksClient.getProjectId(); + + // The zone of the secondary disk. + // secondaryLocation = 'us-central1-a'; + + // The name of the secondary disk. + // secondaryDiskName = 'secondary-disk-name'; + + // The project of the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone of the primary disk. + // primaryLocation = 'us-central1-a'; + + // The name of the primary disk. + // primaryDiskName = 'primary-disk-name'; + + // Start replication + async function callStartReplication() { + const [response] = await disksClient.startAsyncReplication({ + project: secondaryProjectId, + zone: primaryLocation, + disk: primaryDiskName, + disksStartAsyncReplicationRequestResource: + new compute.DisksStartAsyncReplicationRequest({ + asyncSecondaryDisk: `projects/${primaryProjectId}/zones/${secondaryLocation}/disks/${secondaryDiskName}`, + }), + }); + + let operation = response.latestResponse; + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: secondaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log( + `Data replication from primary disk: ${primaryDiskName} to secondary disk: ${secondaryDiskName} started.` + ); + } + + await callStartReplication(); + // [END compute_disk_start_replication] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/disks/stopReplication.js b/compute/disks/stopReplication.js new file mode 100644 index 0000000000..845b1463b2 --- /dev/null +++ b/compute/disks/stopReplication.js @@ -0,0 +1,70 @@ +/* + * 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(primaryDiskName, primaryLocation) { + // [START compute_disk_stop_replication] + // Import the Compute library + const computeLib = require('@google-cloud/compute'); + + // Instantiate a diskClient + const disksClient = new computeLib.DisksClient(); + // Instantiate a zoneOperationsClient + const zoneOperationsClient = new computeLib.ZoneOperationsClient(); + + /** + * TODO(developer): Update/uncomment these variables before running the sample. + */ + // The project that contains the primary disk. + const primaryProjectId = await disksClient.getProjectId(); + + // The zone of the primary disk. + // primaryLocation = 'us-central1-a'; + + // The name of the primary disk. + // primaryDiskName = 'primary-disk-name'; + + // Stop replication + async function callStopReplication() { + const [response] = await disksClient.stopAsyncReplication({ + project: primaryProjectId, + zone: primaryLocation, + disk: primaryDiskName, + }); + + let operation = response.latestResponse; + + // Wait for the operation to complete. + while (operation.status !== 'DONE') { + [operation] = await zoneOperationsClient.wait({ + operation: operation.name, + project: primaryProjectId, + zone: operation.zone.split('/').pop(), + }); + } + + console.log(`Replication for primary disk: ${primaryDiskName} stopped.`); + } + + await callStopReplication(); + // [END compute_disk_stop_replication] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/compute/test/createZonalSecondaryDisk.test.js b/compute/test/zonalSecondaryDisk.test.js similarity index 78% rename from compute/test/createZonalSecondaryDisk.test.js rename to compute/test/zonalSecondaryDisk.test.js index 860f3ce299..09765ab4dd 100644 --- a/compute/test/createZonalSecondaryDisk.test.js +++ b/compute/test/zonalSecondaryDisk.test.js @@ -57,7 +57,7 @@ async function createDisk(diskName, zone) { console.log(`Disk: ${diskName} created.`); } -describe('Create compute zonal secondary disk', async () => { +describe('Compute zonal secondary disk', async () => { const prefix = 'zonal-disk'; const secondaryDiskName = `${prefix}-secondary-${uuid.v4()}`; const primaryDiskName = `${prefix}-primary-${uuid.v4()}`; @@ -86,4 +86,34 @@ describe('Create compute zonal secondary disk', async () => { assert(response.includes(`Secondary disk: ${secondaryDiskName} created.`)); }); + + it('should start replication', () => { + const response = execSync( + `node ./disks/startReplication.js ${secondaryDiskName} ${secondaryZone} ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert( + response.includes( + `Data replication from primary disk: ${primaryDiskName} to secondary disk: ${secondaryDiskName} started.` + ) + ); + }); + + it('should stop replication', () => { + const response = execSync( + `node ./disks/stopReplication.js ${primaryDiskName} ${primaryZone}`, + { + cwd, + } + ); + + assert( + response.includes( + `Replication for primary disk: ${primaryDiskName} stopped.` + ) + ); + }); });