Skip to content

Commit 5313067

Browse files
Jon Wayne Parrottjmdobry
Jon Wayne Parrott
authored andcommitted
Adding GKE tutorial step (GoogleCloudPlatform#60)
1 parent 3247271 commit 5313067

34 files changed

+3379
-0
lines changed
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2015 Google Inc. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
node_modules
16+
.dockerignore
17+
Dockerfile
18+
npm-debug.log
19+
.git
20+
.hg
21+
.svn

optional-container-engine/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
*.log
3+
config.json

optional-container-engine/Dockerfile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Dockerfile extending the generic Node image with application files for a
2+
# single application.
3+
FROM gcr.io/google_appengine/nodejs
4+
# Check to see if the the version included in the base runtime satisfies
5+
# '>=0.12.7', if not then do an npm install of the latest available
6+
# version that satisfies it.
7+
RUN /usr/local/bin/install_node '>=0.12.7'
8+
COPY . /app/
9+
# You have to specify "--unsafe-perm" with npm install
10+
# when running as root. Failing to do this can cause
11+
# install to appear to succeed even if a preinstall
12+
# script fails, and may have other adverse consequences
13+
# as well.
14+
# This command will also cat the npm-debug.log file after the
15+
# build, if it exists.
16+
RUN npm install --unsafe-perm || \
17+
((if [ -f npm-debug.log ]; then \
18+
cat npm-debug.log; \
19+
fi) && false)
20+
CMD npm start

optional-container-engine/Makefile

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
GCLOUD_PROJECT:=$(shell gcloud config list project --format="value(core.project)")
2+
3+
.PHONY: all
4+
all: deploy
5+
6+
.PHONY: create-cluster
7+
create-cluster:
8+
gcloud container clusters create bookshelf \
9+
--scope "cloud-platform" \
10+
--num-nodes 2
11+
gcloud container clusters get-credentials bookshelf
12+
13+
.PHONY: create-bucket
14+
create-bucket:
15+
gsutil mb gs://$(GCLOUD_PROJECT)
16+
gsutil defacl set public-read gs://$(GCLOUD_PROJECT)
17+
18+
.PHONY: build
19+
build:
20+
docker build -t gcr.io/$(GCLOUD_PROJECT)/bookshelf .
21+
22+
.PHONY: push
23+
push: build
24+
gcloud docker push gcr.io/$(GCLOUD_PROJECT)/bookshelf
25+
26+
.PHONY: template
27+
template:
28+
sed -i ".tmpl" "s/\$$GCLOUD_PROJECT/$(GCLOUD_PROJECT)/g" bookshelf-frontend.yaml
29+
sed -i ".tmpl" "s/\$$GCLOUD_PROJECT/$(GCLOUD_PROJECT)/g" bookshelf-worker.yaml
30+
31+
.PHONY: create-service
32+
create-service:
33+
kubectl create -f bookshelf-service.yaml
34+
35+
.PHONY: deploy-frontend
36+
deploy-frontend: push template
37+
kubectl create -f bookshelf-frontend.yaml
38+
39+
.PHONY: deploy-worker
40+
deploy-worker: push template
41+
kubectl create -f bookshelf-worker.yaml
42+
43+
.PHONY: deploy
44+
deploy: deploy-frontend deploy-worker create-service
45+
46+
.PHONY: delete
47+
delete:
48+
-kubectl delete -f bookshelf-frontend.yaml
49+
-kubectl delete -f bookshelf-worker.yaml
50+
-kubectl delete -f bookshelf-frontend.yaml

optional-container-engine/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Deploy Bookshelf to Container Engine/Kubernetes
2+
3+
This optional tutorial will walk you through how to deploy the Bookshelf sample application to [Google Container Engine](https://cloud.google.com/container-engine/). This tutorial is also applicable to [Kubernetes](http://kubernetes.io/) outside of Container Engine, but may require additional steps for external load balancing.
4+
5+
Please refer to the [Tutorial](https://cloud.google.com/nodejs/tutorials/bookshelf-on-container-engine) for instructions on how to deploy this sample.

optional-container-engine/app.js

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2015-2016, Google, Inc.
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
// Activate Google Cloud Trace and Debug when in production
17+
if (process.env.NODE_ENV === 'production') {
18+
require('@google/cloud-trace').start();
19+
require('@google/cloud-debug');
20+
}
21+
22+
var path = require('path');
23+
var express = require('express');
24+
var session = require('express-session');
25+
var MemcachedStore = require('connect-memcached')(session);
26+
var passport = require('passport');
27+
var config = require('./config');
28+
var logging = require('./lib/logging');
29+
30+
var app = express();
31+
32+
app.disable('etag');
33+
app.set('views', path.join(__dirname, 'views'));
34+
app.set('view engine', 'jade');
35+
app.set('trust proxy', true);
36+
37+
// Add the request logger before anything else so that it can
38+
// accurately log requests.
39+
app.use(logging.requestLogger);
40+
41+
// Configure the session and session storage.
42+
var sessionConfig = {
43+
resave: false,
44+
saveUninitialized: false,
45+
secret: config.get('SECRET'),
46+
signed: true
47+
};
48+
49+
// In production use the App Engine Memcache instance to store session data,
50+
// otherwise fallback to the default MemoryStore in development.
51+
if (config.get('NODE_ENV') === 'production') {
52+
sessionConfig.store = new MemcachedStore({
53+
hosts: [config.get('MEMCACHE_URL')]
54+
});
55+
}
56+
57+
app.use(session(sessionConfig));
58+
59+
// OAuth2
60+
app.use(passport.initialize());
61+
app.use(passport.session());
62+
app.use(require('./lib/oauth2').router);
63+
64+
// Books
65+
app.use('/books', require('./books/crud'));
66+
app.use('/api/books', require('./books/api'));
67+
68+
// Redirect root to /books
69+
app.get('/', function (req, res) {
70+
res.redirect('/books');
71+
});
72+
73+
// Our application will need to respond to health checks when running on
74+
// Compute Engine with Managed Instance Groups.
75+
app.get('/_ah/health', function (req, res) {
76+
res.status(200).send('ok');
77+
});
78+
79+
// Add the error logger after all middleware and routes so that
80+
// it can log errors from the whole application. Any custom error
81+
// handlers should go after this.
82+
app.use(logging.errorLogger);
83+
84+
// Basic 404 handler
85+
app.use(function (req, res) {
86+
res.status(404).send('Not Found');
87+
});
88+
89+
// Basic error handler
90+
app.use(function (err, req, res, next) {
91+
/* jshint unused:false */
92+
// If our routes specified a specific response, then send that. Otherwise,
93+
// send a generic message so as not to leak anything.
94+
res.status(500).send(err.response || 'Something broke!');
95+
});
96+
97+
if (module === require.main) {
98+
// Start the server
99+
var server = app.listen(config.get('PORT'), function () {
100+
var port = server.address().port;
101+
console.log('App listening on port %s', port);
102+
});
103+
}
104+
105+
module.exports = app;
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright 2015-2016, Google, Inc.
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
var express = require('express');
17+
var bodyParser = require('body-parser');
18+
var config = require('../config');
19+
20+
function getModel () {
21+
return require('./model-' + config.get('DATA_BACKEND'));
22+
}
23+
24+
var router = express.Router();
25+
26+
// Automatically parse request body as JSON
27+
router.use(bodyParser.json());
28+
29+
/**
30+
* GET /api/books
31+
*
32+
* Retrieve a page of books (up to ten at a time).
33+
*/
34+
router.get('/', function list (req, res, next) {
35+
getModel().list(10, req.query.pageToken, function (err, entities, cursor) {
36+
if (err) {
37+
return next(err);
38+
}
39+
res.json({
40+
items: entities,
41+
nextPageToken: cursor
42+
});
43+
});
44+
});
45+
46+
/**
47+
* POST /api/books
48+
*
49+
* Create a new book.
50+
*/
51+
router.post('/', function insert (req, res, next) {
52+
getModel().create(req.body, true, function (err, entity) {
53+
if (err) {
54+
return next(err);
55+
}
56+
res.json(entity);
57+
});
58+
});
59+
60+
/**
61+
* GET /api/books/:id
62+
*
63+
* Retrieve a book.
64+
*/
65+
router.get('/:book', function get (req, res, next) {
66+
getModel().read(req.params.book, function (err, entity) {
67+
if (err) {
68+
return next(err);
69+
}
70+
res.json(entity);
71+
});
72+
});
73+
74+
/**
75+
* PUT /api/books/:id
76+
*
77+
* Update a book.
78+
*/
79+
router.put('/:book', function update (req, res, next) {
80+
getModel().update(req.params.book, req.body, true, function (err, entity) {
81+
if (err) {
82+
return next(err);
83+
}
84+
res.json(entity);
85+
});
86+
});
87+
88+
/**
89+
* DELETE /api/books/:id
90+
*
91+
* Delete a book.
92+
*/
93+
router.delete('/:book', function _delete (req, res, next) {
94+
getModel().delete(req.params.book, function (err) {
95+
if (err) {
96+
return next(err);
97+
}
98+
res.status(200).send('OK');
99+
});
100+
});
101+
102+
/**
103+
* Errors on "/api/books/*" routes.
104+
*/
105+
router.use(function handleRpcError (err, req, res, next) {
106+
// Format error and forward to generic error handler for logging and
107+
// responding to the request
108+
err.response = {
109+
message: err.message,
110+
internalCode: err.code
111+
};
112+
next(err);
113+
});
114+
115+
module.exports = router;

0 commit comments

Comments
 (0)