Skip to content
This repository has been archived by the owner on Jul 13, 2023. It is now read-only.

Commit

Permalink
feat: add vm.update() method (#478)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenplusplus committed Aug 10, 2020
1 parent 1d3a41a commit 7bcb79c
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/vm.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
'use strict';

const common = require('@google-cloud/common');
const extend = require('extend');
const format = require('string-format-obj');
const is = require('is');
const {promisifyAll} = require('@google-cloud/promisify');
Expand Down Expand Up @@ -920,6 +921,64 @@ class VM extends common.ServiceObject {
callback || common.util.noop
);
}
/**
* Update the instance.
*
* NOTE: This method will pull the latest record of the current metadata, then
* merge it with the object you provide. This means there is a chance of a
* mismatch in data if the resource is updated immediately after we pull the
* metadata, but before we update it.
*
* @see [Instances: update API Documentation]{@link https://cloud.google.com/compute/docs/reference/v1/instances/update}
*
* @param {function=} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {Operation} callback.operation - An operation object
* that can be used to check the status of the request.
* @param {object} callback.apiResponse - The full API response.
*
* @example
* const Compute = require('@google-cloud/compute');
* const compute = new Compute();
* const zone = compute.zone('zone-name');
* const vm = zone.vm('vm-name');
*
* const metadata = {
* deletionProtection: false,
* };
*
* vm.update(metadata, function(err, operation, apiResponse) {
* // `operation` is an Operation object that can be used to check the
* // status of the request.
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* vm.update(metadata).then(function(data) {
* const operation = data[0];
* const apiResponse = data[1];
* });
*/
update(metadata, callback) {
callback = callback || common.util.noop;

this.getMetadata((err, currentMetadata) => {
if (err) {
callback(err);
return;
}

this.request(
{
method: 'PUT',
uri: '',
json: extend(true, currentMetadata, metadata),
},
callback
);
});
}
/**
* This function will callback when the VM is in the specified state.
*
Expand Down
6 changes: 6 additions & 0 deletions system-test/compute.js
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,12 @@ describe('Compute', () => {
assert.deepStrictEqual(vm.metadata.metadata.items, [{key, value}]);
});

it('should update the VM', async () => {
await awaitResult(vm.update({deletionProtection: false}));
const [metadata] = await vm.getMetadata();
assert.strictEqual(metadata.deletionProtection, false);
});

it('should allow updating old metadata', async () => {
const key = 'newKey';
const value = 'newValue';
Expand Down
89 changes: 89 additions & 0 deletions test/vm.js
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,95 @@ describe('VM', () => {
});
});

describe('update', () => {
const CURRENT_METADATA = {currentProperty: true};
const METADATA = {newProperty: true};

beforeEach(() => {
vm.getMetadata = callback => {
callback(null, CURRENT_METADATA);
};
vm.request = () => {};
});

it('should pull the latest metadata', done => {
vm.getMetadata = () => {
done();
};

vm.update(METADATA, assert.ifError);
});

it('should return an error if the metadata call failed', done => {
const error = new Error('Error.');

vm.getMetadata = callback => {
callback(error);
};

vm.update(METADATA, err => {
assert.strictEqual(err, error);
done();
});
});

it('should send the correct request', done => {
vm.request = reqOpts => {
assert.deepStrictEqual(reqOpts, {
method: 'PUT',
uri: '',
json: extend(true, CURRENT_METADATA, METADATA),
});
done();
};

vm.update(METADATA, assert.ifError);
});

it('should deep merge the current metadata with new metadata', done => {
const currentMetadata = {
a: {
b: {
c: true,
d: true,
},
},
};
const newMetadata = {
a: {
b: {
c: false,
},
},
};
const expectedMetadata = {
a: {
b: {
c: false,
d: true,
},
},
};

vm.getMetadata = callback => {
callback(null, currentMetadata);
};

vm.request = reqOpts => {
assert.deepStrictEqual(reqOpts.json, expectedMetadata);
done();
};

vm.update(newMetadata, assert.ifError);
});

it('should not require a callback', () => {
assert.doesNotThrow(() => {
vm.update(METADATA);
});
});
});

describe('waitFor', () => {
const VALID_STATUSES = [
'PROVISIONING',
Expand Down

0 comments on commit 7bcb79c

Please sign in to comment.