Skip to content

Adding Google Cloud Memorystore sample #1474

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 4 commits into from
May 9, 2018
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
15 changes: 15 additions & 0 deletions memorystore/redis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Getting started with Googe Cloud Memorystore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can automatically generate READMEs using our README templater, assuming this isn't a special case. Please reach out to me or Jon for help using it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be perfect. Please let me know how to do that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed we'll address this in a follow-up CL to not block the docs rolling out today.

Simple HTTP server example to demonstrate connecting to [Google Cloud Memorystore](https://cloud.google.com/memorystore/docs/redis).
This sample uses the [redis-py client](https://github.com/andymccurdy/redis-py).

## Running on GCE

Follow the instructions in [this guide](https://cloud.google.com/memorystore/docs/redis/connect-redis-instance-gce) to deploy the sample application on a GCE VM.

## Running on GKE

Follow the instructions in [this guide](https://cloud.google.com/memorystore/docs/redis/connect-redis-instance-gke) to deploy the sample application on GKE.

## Running on Google App Engine Flex

Follow the instructions in [this guide](https://cloud.google.com/memorystore/docs/redis/connect-redis-instance-flex) to deploy the sample application on GAE Flex.
31 changes: 31 additions & 0 deletions memorystore/redis/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 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 memorystore_app_yaml]
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
python_version: 3

# update with Redis instance host IP, port
env_variables:
REDISHOST: redis-ip
REDISPORT: 6379

# update with Redis instance network name
network:
name: default

#[END memorystore_app_yaml]
58 changes: 58 additions & 0 deletions memorystore/redis/gce_deployment/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash

# 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 memorystore_deploy_sh]
if [ -z "$REDISHOST" ]; then
echo "Must set \$REDISHOST. For example: REDISHOST=127.0.0.1"
exit 1
fi

if [ -z "$REDISPORT" ]; then
echo "Must set \$REDISPORT. For example: REDISPORT=6379"
exit 1
fi

if [ -z "$GCS_APP_LOCATION" ]; then
echo "Must set \$GCS_APP_LOCATION. For example: GCS_APP_LOCATION=gs://my-bucket/app"
exit 1
fi

if [ -z "$ZONE" ]; then
ZONE=$(gcloud config get-value compute/zone -q)
echo $ZONE
fi

#Upload the tar to GCS
tar -cvf app.tar -C .. requirements.txt main.py
# Copy to GCS bucket
gsutil cp app.tar $GCS_APP_LOCATION

# Create an instance
gcloud compute instances create my-instance \
--image-family=debian-8 \
--image-project=debian-cloud \
--machine-type=g1-small \
--scopes cloud-platform \
--metadata-from-file startup-script=startup-script.sh \
--metadata app-location=$GCS_APP_LOCATION,redis-host=$REDISHOST,redis-port=$REDISPORT \
--zone $ZONE \
--tags http-server

gcloud compute firewall-rules create allow-http-server-8080 \
--allow tcp:8080 \
--source-ranges 0.0.0.0/0 \
--target-tags http-server \
--description "Allow port 8080 access to http-server"
# [END memorystore_deploy_sh]
65 changes: 65 additions & 0 deletions memorystore/redis/gce_deployment/startup-script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#! /bin/bash

# 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 memorystore_startup_script_sh]
set -v

# Talk to the metadata server to get the project id and location of application binary.
PROJECTID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
GCS_APP_LOCATION=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/app-location" -H "Metadata-Flavor: Google")
REDISHOST=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/redis-host" -H "Metadata-Flavor: Google")
REDISPORT=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/redis-port" -H "Metadata-Flavor: Google")

# Install dependencies from apt
apt-get update
apt-get install -yq \
git build-essential supervisor python python-dev python-pip libffi-dev \
libssl-dev

# Install logging monitor. The monitor will automatically pickup logs send to
# syslog.
curl -s "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh" | bash
service google-fluentd restart &

gsutil cp $GCS_APP_LOCATION /app.tar
mkdir -p /app
tar -x -f /app.tar -C /app
cd /app

# Install the app dependencies
pip install --upgrade pip virtualenv
virtualenv /app/env
/app/env/bin/pip install -r /app/requirements.txt

# Create a pythonapp user. The application will run as this user.
getent passwd pythonapp || useradd -m -d /home/pythonapp pythonapp
chown -R pythonapp:pythonapp /app

# Configure supervisor to run the Go app.
cat >/etc/supervisor/conf.d/pythonapp.conf << EOF
[program:pythonapp]
directory=/app
environment=HOME="/home/pythonapp",USER="pythonapp",REDISHOST=$REDISHOST,REDISPORT=$REDISPORT
command=/app/env/bin/gunicorn main:app --bind 0.0.0:8080
autostart=true
autorestart=true
user=pythonapp
stdout_logfile=syslog
stderr_logfile=syslog
EOF

supervisorctl reread
supervisorctl update
# [END memorystore_startup_script_sh]
20 changes: 20 additions & 0 deletions memorystore/redis/gce_deployment/teardown.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

# 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 memorystore_teardown_sh]
gcloud compute instances delete my-instance

gcloud compute firewall-rules delete allow-http-server-8080
# [END memorystore_teardown_sh]
30 changes: 30 additions & 0 deletions memorystore/redis/gke_deployment/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# The Google App Engine python runtime is Debian Jessie with Python installed
# and various os-level packages to allow installation of popular Python
# libraries. The source is on github at:
# https://github.com/GoogleCloudPlatform/python-docker
FROM gcr.io/google_appengine/python

# Create a virtualenv for the application dependencies.
# If you want to use Python 2, add the -p python2.7 flag.
RUN virtualenv -p python3.4 /env

# Set virtualenv environment variables. This is equivalent to running
# source /env/bin/activate. This ensures the application is executed within
# the context of the virtualenv and will have access to its dependencies.
ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH

# Note: REDISHOST value here is only used for local testing
# See README.md on how to inject environment variable as ConfigMap on GKE
ENV REDISHOST 127.0.0.1
ENV REDISPORT 6379

# Install dependencies.
ADD requirements.txt /app/requirements.txt
RUN pip install -r /app/requirements.txt

# Add application code.
ADD . /app

CMD ["gunicorn", "-b", "0.0.0.0:8080", "main:app"]

39 changes: 39 additions & 0 deletions memorystore/redis/gke_deployment/visit-counter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: visit-counter
labels:
app: visit-counter
spec:
replicas: 1
template:
metadata:
labels:
app: visit-counter
spec:
containers:
- name: visit-counter
image: "gcr.io/<PROJECT-ID>/visit-counter:v1"
env:
- name: REDISHOST
valueFrom:
configMapKeyRef:
name: redishost
key: REDISHOST
ports:
- name: http
containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: visit-counter
spec:
type: LoadBalancer
selector:
app: visit-counter
ports:
- port: 80
targetPort: 8080
protocol: TCP

46 changes: 46 additions & 0 deletions memorystore/redis/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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 memorystore_main_py]
import logging
import os

from flask import Flask
import redis

app = Flask(__name__)

redis_host = os.environ.get('REDISHOST', 'localhost')
redis_port = int(os.environ.get('REDISPORT', 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port)


@app.route('/')
def index():
value = redis_client.incr('counter', 1)
return 'Visitor number: {}'.format(value)


@app.errorhandler(500)
def server_error(e):
logging.exception('An error occurred during a request.')
return """
An internal error occurred: <pre>{}</pre>
See logs for full stacktrace.
""".format(e), 500


if __name__ == '__main__':
# This is used when running locally. Gunicorn is used to run the
# application on Google App Engine. See entrypoint in app.yaml.
app.run(host='127.0.0.1', port=8080, debug=True)
# [END memorystore_main_py]
17 changes: 17 additions & 0 deletions memorystore/redis/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 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 memorystore_requirements]
Flask==0.12.2
gunicorn==19.7.1
redis==2.10.5
# [END memorystore_requirements]