Skip to content

NodeJS 6 code sample for Cloud Function to start/stop GCE instances #815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 2, 2018
141 changes: 141 additions & 0 deletions functions/scheduleinstance/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// [START functions_start_instance_http]
// [START functions_stop_instance_http]
const Compute = require('@google-cloud/compute');
const compute = new Compute();

// [END functions_stop_instance_http]
/**
* Starts a Compute Engine instance.
*
* Expects an HTTP POST request with a request body containing the following
* attributes:
* zone - the GCP zone the instance is located in.
* instance - the name of the instance.
*
* @param {!object} req Cloud Function HTTP request data.
* @param {!object} res Cloud Function HTTP response data.
* @returns {!object} Cloud Function response data with status code and message.
*/
exports.startInstance = (req, res) => {
try {
const reqBody = _validateReqBody(_parseReqBody(_validateReq(req)));
compute.zone(reqBody.zone)
.vm(reqBody.instance)
.start()
.then(data => {
// Operation pending.
const operation = data[0];
return operation.promise();
})
.then(() => {
// Operation complete. Instance successfully started.
const message = 'Successfully started instance ' + reqBody.instance;
console.log(message);
res.status(200).send(message);
})
.catch(err => {
console.log(err);
res.status(500).send({error: err.message});
});
} catch (err) {
console.log(err);
res.status(400).send({error: err.message});
}
return res;
};
// [END functions_start_instance_http]

// [START functions_stop_instance_http]
/**
* Stops a Compute Engine instance.
*
* Expects an HTTP POST request with a request body containing the following
* attributes:
* zone - the GCP zone the instance is located in.
* instance - the name of the instance.
*
* @param {!object} req Cloud Function HTTP request data.
* @param {!object} res Cloud Function HTTP response data.
* @returns {!object} Cloud Function response data with status code and message.
*/
exports.stopInstance = (req, res) => {
try {
const reqBody = _validateReqBody(_parseReqBody(_validateReq(req)));
compute.zone(reqBody.zone)
.vm(reqBody.instance)
.stop()
.then(data => {
// Operation pending.
const operation = data[0];
return operation.promise();
})
.then(() => {
// Operation complete. Instance successfully stopped.
const message = 'Successfully stopped instance ' + reqBody.instance;
console.log(message);
res.status(200).send(message);
})
.catch(err => {
console.log(err);
res.status(500).send({error: err.message});
});
} catch (err) {
console.log(err);
res.status(400).send({error: err.message});
}
return res;
};
// [START functions_start_instance_http]

/**
* Parses the request body attributes of an HTTP request based on content-type.
*
* @param {!object} req a Cloud Functions HTTP request object.
* @returns {!object} an object with attributes matching the HTTP request body.
*/
function _parseReqBody (req) {
const contentType = req.get('content-type');
if (contentType === 'application/json') {
// Request.body automatically parsed as an object.
return req.body;
} else if (contentType === 'application/octet-stream') {
// Convert buffer to a string and parse as JSON string.
return JSON.parse(req.body.toString());
} else {
throw new Error('Unsupported HTTP content-type ' + req.get('content-type') +
'; use application/json or application/octet-stream');
}
}

/**
* Validates that a request body contains the expected fields.
*
* @param {!object} reqBody the request body to validate.
* @returns {!object} the request body object.
*/
function _validateReqBody (reqBody) {
if (!reqBody.zone) {
throw new Error(`Attribute 'zone' missing from POST request`);
} else if (!reqBody.instance) {
throw new Error(`Attribute 'instance' missing from POST request`);
}
return reqBody;
}

/**
* Validates that a HTTP request contains the expected fields.
*
* @param {!object} req the request to validate.
* @returns {!object} the request object.
*/
function _validateReq (req) {
if (req.method !== 'POST') {
throw new Error('Unsupported HTTP method ' + req.method +
'; use method POST');
} else if (typeof req.get('content-type') === 'undefined') {
throw new Error('HTTP content-type missing');
}
return req;
}
// [END functions_start_instance_http]
// [END functions_stop_instance_http]
29 changes: 29 additions & 0 deletions functions/scheduleinstance/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "schedule-instance",
"version": "0.0.1",
"private": true,
"license": "Apache-2.0",
"author": "Google Inc.",
"repository": {
"type": "git",
"url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
},
"engines": {
"node": ">=6.0"
},
"scripts": {
"lint": "repo-tools lint",
"pretest": "npm run lint",
"test": "ava -T 20s --verbose test/*.test.js"
},
"devDependencies": {
"@google-cloud/nodejs-repo-tools": "2.2.1",
"ava": "0.25.0",
"proxyquire": "2.0.0",
"sinon": "4.4.2"
},
"dependencies": {
"@google-cloud/compute": "^0.10.0",
"safe-buffer": "5.1.1"
}
}
Loading