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

feat: add VM.get/setLabels() methods #515

Merged
merged 6 commits into from
Nov 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions src/vm.js
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,44 @@ class VM extends common.ServiceObject {
});
});
}
/**
* Get the instance's labels and their fingerprint.
*
* This method wraps {module:compute/vm#getMetadata}, returning only the `labels`
* property.
*
* @param {function} callback - The callback function.
* @param {?error} callback.err - An error returned while making this request.
* @param {object[]} callback.labels - Label objects from this VM.
* @param {string} callback.fingerprint - The current label fingerprint.
* @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');
*
* vm.getLabels(function(err, labels, fingerprint, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* vm.getLabels().then(function(data) {
* const labels = data[0];
* const fingerprint = data[1];
* const apiResponse = data[2];
* });
*/
getLabels(callback) {
this.getMetadata((err, metadata, apiResponse) => {
if (err) {
callback(err, null, null, apiResponse);
return;
}
callback(null, metadata.labels, metadata.labelFingerprint, apiResponse);
});
}
/**
* Returns the serial port output for the instance.
*
Expand Down Expand Up @@ -721,6 +759,56 @@ class VM extends common.ServiceObject {
})
);
}
/**
* Set labels for this instance.
*
* @see [Instances: setLabels API Documentation]{@link https://cloud.google.com/compute/docs/reference/v1/instances/setLabels}
*
* @param {object} labels - New labels.
* @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 labels = {
* 'startup-script': '...',
* customKey: null // Setting `null` will remove the `customKey` property.
* };
*
* vm.setLabels(labels, 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.setLabels(labels).then(function(data) {
* const operation = data[0];
* const apiResponse = data[1];
* });
*/
setLabels(labels, labelFingerprint, callback) {
const body = {
labels: labels,
labelFingerprint: labelFingerprint,
};
this.request(
{
method: 'POST',
uri: '/setLabels',
json: body,
},
callback || common.util.noop
);
}
/**
* Set the custom metadata for this instance.
*
Expand Down
7 changes: 7 additions & 0 deletions system-test/compute.js
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,13 @@ describe('Compute', () => {
return vm.getSerialPortOutput();
});

it('should set labels', async () => {
let [labels, fingerprint] = await vm.getLabels();
await awaitResult(vm.setLabels({foo: 'bar'}, fingerprint));
[labels, fingerprint] = await vm.getLabels();
assert.strictEqual(labels.foo, 'bar');
});

it('should set tags', async () => {
const newTagName = 'new-tag';
const [tags, fingerprint] = await vm.getTags();
Expand Down
86 changes: 86 additions & 0 deletions test/vm.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,65 @@ describe('VM', () => {
});
});

describe('getLabels', () => {
it('should get metadata', done => {
vm.getMetadata = function () {
done();
};

vm.getTags(assert.ifError);
});

describe('error', () => {
const error = new Error('Error.');
const apiResponse = {a: 'b', c: 'd'};

beforeEach(() => {
vm.getMetadata = function (callback) {
callback(error, null, apiResponse);
};
});

it('should execute callback with error', done => {
vm.getLabels((err, labels, fingerprint, apiResponse_) => {
assert.strictEqual(err, error);
assert.strictEqual(labels, null);
assert.strictEqual(fingerprint, null);
assert.strictEqual(apiResponse_, apiResponse);

done();
});
});
});

describe('success', () => {
const metadata = {
labels: {},
labelFingerprint: 'fingerprint',
};

const apiResponse = {a: 'b', c: 'd'};

beforeEach(() => {
vm.getMetadata = function (callback) {
callback(null, metadata, apiResponse);
};
});

it('should execute callback with tags and fingerprint', done => {
vm.getLabels((err, labels, fingerprint, apiResponse_) => {
assert.ifError(err);

assert.strictEqual(labels, metadata.labels);
assert.strictEqual(fingerprint, metadata.labelFingerprint);
assert.strictEqual(apiResponse_, apiResponse);

done();
});
});
});
});

describe('getSerialPortOutput', () => {
const EXPECTED_QUERY = {port: 1, start: 0};

Expand Down Expand Up @@ -738,6 +797,33 @@ describe('VM', () => {
});
});

describe('setLabels', () => {
const LABELS = [];
const FINGERPRINT = '';

it('should make the correct request', done => {
vm.request = function (reqOpts, callback) {
assert.strictEqual(reqOpts.method, 'POST');
assert.strictEqual(reqOpts.uri, '/setLabels');
assert.strictEqual(reqOpts.json.labels, LABELS);
assert.strictEqual(reqOpts.json.labelFingerprint, FINGERPRINT);

callback(); // done()
};

vm.setLabels(LABELS, FINGERPRINT, done);
});

it('should not require a callback', done => {
vm.request = function (reqOpts, callback) {
assert.doesNotThrow(callback);
done();
};

vm.setLabels(LABELS, FINGERPRINT);
});
});

describe('setMetadata', () => {
const METADATA = {
newKey: 'newValue',
Expand Down