-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add sample for managing GCE instances from GCF (#815)
NodeJS 6 code sample for Cloud Function to start/stop GCE instances.
- Loading branch information
Showing
5 changed files
with
524 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Format: //devtools/kokoro/config/proto/build.proto | ||
|
||
# Set the folder in which the tests are run | ||
env_vars: { | ||
key: "PROJECT" | ||
value: "functions/scheduleinstance" | ||
} | ||
|
||
# Tell the trampoline which build file to use. | ||
env_vars: { | ||
key: "TRAMPOLINE_BUILD_FILE" | ||
value: "github/nodejs-docs-samples/.kokoro/build.sh" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/> | ||
|
||
# Google Cloud Functions - Scheduling GCE Instances sample | ||
|
||
## Deploy and run the sample | ||
|
||
See the [Scheduling Instances with Cloud Scheduler tutorial][tutorial]. | ||
|
||
[tutorial]: https://cloud.google.com/scheduler/docs/scheduling-instances-with-cloud-scheduler | ||
|
||
## Run the tests | ||
|
||
1. Read and follow the [prerequisites](../../#how-to-run-the-tests). | ||
|
||
1. Install dependencies: | ||
|
||
npm install | ||
|
||
1. Run the tests: | ||
|
||
npm test | ||
|
||
## Additional resources | ||
|
||
* [Cloud Scheduler documentation][docs] | ||
* [HTTP Cloud Functions documentation][http_docs] | ||
* [HTTP Cloud Functions tutorial][http_tutorial] | ||
|
||
[docs]: https://cloud.google.com/scheduler/docs/ | ||
[http_docs]: https://cloud.google.com/functions/docs/writing/http | ||
[http_tutorial]: https://cloud.google.com/functions/docs/tutorials/http |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/** | ||
* Copyright 2018, Google, Inc. | ||
* 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. | ||
*/ | ||
|
||
// [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] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
Oops, something went wrong.