Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a09ca74

Browse filesBrowse files
dinagravesbusunkim96
authored andcommitted
Adding Cloud run system package sample (GoogleCloudPlatform#2554)
1 parent cce0c9d commit a09ca74
Copy full SHA for a09ca74

File tree

Expand file treeCollapse file tree

8 files changed

+230
-0
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+230
-0
lines changed

‎noxfile-template.py

Copy file name to clipboardExpand all lines: noxfile-template.py
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ def _setup_appengine_sdk(session):
149149
or str(Path(sample).absolute().relative_to(REPO_ROOT)).startswith(
150150
"bigquery/pandas-gbq-migration"
151151
)
152+
or str(Path(sample).absolute().relative_to(REPO_ROOT)).startswith(
153+
"run/system-package"
154+
)
152155
)
153156
]
154157
NON_GAE_STANDARD_SAMPLES_PY2 = sorted(
@@ -207,6 +210,7 @@ def py3(session, sample):
207210
"""Runs py.test for a sample using Python 3.x"""
208211
_session_tests(session, sample)
209212

213+
210214
@nox.session(python="3.6")
211215
def lint(session):
212216
session.install("flake8", "flake8-import-order")
@@ -219,6 +223,7 @@ def lint(session):
219223
]
220224
session.run("flake8", *args)
221225

226+
222227
SAMPLES_WITH_GENERATED_READMES = sorted(list(_collect_dirs(".", suffix=".rst.in")))
223228

224229

‎noxfile.py

Copy file name to clipboardExpand all lines: noxfile.py
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ def _setup_appengine_sdk(session):
174174
sample.startswith("./appengine/standard_python37")
175175
or sample.startswith("./functions/")
176176
or sample.startswith("./bigquery/pandas-gbq-migration")
177+
or sample.startswith("./run/system-package")
177178
)
178179
]
179180
NON_GAE_STANDARD_SAMPLES_PY2 = sorted(

‎run/system-package/.dockerignore

Copy file name to clipboard
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Dockerfile
2+
.dockerignore
3+
__pycache__
4+
.pytest_cache

‎run/system-package/Dockerfile

Copy file name to clipboard
+42Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2019 Google, LLC.
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+
# Use the official Python image.
16+
# https://hub.docker.com/_/python
17+
FROM python:3.7
18+
19+
# [START run_system_package_ubuntu]
20+
RUN apt-get update -y && apt-get install -y \
21+
graphviz \
22+
&& apt-get clean
23+
# [END run_system_package_ubuntu]
24+
25+
# Copy application dependency manifests to the container image.
26+
# Copying this separately prevents re-running pip install on every code change.
27+
COPY requirements.txt .
28+
29+
# Install production dependencies.
30+
RUN pip install -r requirements.txt
31+
32+
# Copy local code to the container image.
33+
ENV APP_HOME /app
34+
WORKDIR $APP_HOME
35+
COPY . .
36+
37+
# Run the web service on container startup.
38+
# Use gunicorn webserver with one worker process and 8 threads.
39+
# For environments with multiple CPU cores, increase the number of workers
40+
# to be equal to the cores available.
41+
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 main:app
42+

‎run/system-package/README.md

Copy file name to clipboard
+44Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Cloud Run System Package Sample
2+
3+
This sample shows how to use a CLI tool installed as a system package as part of a web service.
4+
5+
Use it with the [Using system packages tutorial](https://cloud.google.com/run/docs/tutorials/system-packages).
6+
7+
8+
[![Run in Google Cloud][run_img]][run_link]
9+
10+
[run_img]: https://storage.googleapis.com/cloudrun/button.svg
11+
[run_link]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&cloudshell_working_dir=run/system-package
12+
13+
## Build
14+
15+
```
16+
docker build --tag graphviz:python .
17+
```
18+
19+
## Run Locally
20+
21+
```
22+
docker run --rm -p 9090:8080 graphviz:python
23+
```
24+
25+
## Test
26+
27+
```
28+
pytest
29+
```
30+
31+
_Note: you may need to install `pytest` using `pip install pytest`._
32+
33+
## Deploy
34+
35+
```sh
36+
# Set an environment variable with your GCP Project ID
37+
export GOOGLE_CLOUD_PROJECT=<PROJECT_ID>
38+
39+
# Submit a build using Google Cloud Build
40+
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/graphviz
41+
42+
# Deploy to Cloud Run
43+
gcloud beta run deploy graphviz --image gcr.io/${GOOGLE_CLOUD_PROJECT}/graphviz
44+
```

‎run/system-package/main.py

Copy file name to clipboard
+85Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Copyright 2019 Google, LLC.
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+
from flask import Flask, make_response, request
16+
import os
17+
import subprocess
18+
import sys
19+
20+
21+
app = Flask(__name__)
22+
23+
24+
# [START run_system_package_handler]
25+
@app.route("/diagram.png", methods=["GET"])
26+
def index():
27+
# Takes an HTTP GET request with query param dot and
28+
# returns a png with the rendered DOT diagram in a HTTP response.
29+
try:
30+
image = create_diagram(request.args.get("dot"))
31+
response = make_response(image)
32+
response.headers.set("Content-Type", "image/png")
33+
return response
34+
35+
except Exception as e:
36+
print("error: {}".format(e))
37+
38+
# Flush the stdout to avoid log buffering.
39+
sys.stdout.flush()
40+
41+
# If no graphviz definition or bad graphviz def, return 400
42+
if "syntax" in str(e):
43+
return "Bad Request: {}".format(e), 400
44+
45+
return "Internal Server Error", 500
46+
47+
48+
# [END run_system_package_handler]
49+
50+
51+
# [START run_system_package_exec]
52+
def create_diagram(dot):
53+
# Generates a diagram based on a graphviz DOT diagram description.
54+
if not dot:
55+
raise Exception("syntax: no graphviz definition provided")
56+
57+
dot_args = [ # These args add a watermark to the dot graphic.
58+
"-Glabel=Made on Cloud Run",
59+
"-Gfontsize=10",
60+
"-Glabeljust=right",
61+
"-Glabelloc=bottom",
62+
"-Gfontcolor=gray",
63+
"-Tpng",
64+
]
65+
66+
# Uses local `dot` binary from Graphviz:
67+
# https://graphviz.gitlab.io
68+
image = subprocess.run(
69+
["dot"] + dot_args, input=dot.encode("utf-8"), stdout=subprocess.PIPE
70+
).stdout
71+
72+
if not image:
73+
raise Exception("syntax: bad graphviz definition provided")
74+
return image
75+
76+
77+
# [END run_system_package_exec]
78+
79+
80+
if __name__ == "__main__":
81+
PORT = int(os.getenv("PORT")) if os.getenv("PORT") else 8080
82+
83+
# This is used when running locally. Gunicorn is used to run the
84+
# application on Cloud Run. See entrypoint in Dockerfile.
85+
app.run(host="127.0.0.1", port=PORT, debug=True)

‎run/system-package/main_test.py

Copy file name to clipboard
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2019 Google, LLC.
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+
# NOTE:
16+
# To pass these tests locally, run `brew install graphviz`
17+
18+
19+
import main
20+
import pytest
21+
22+
23+
@pytest.fixture
24+
def client():
25+
main.app.testing = True
26+
return main.app.test_client()
27+
28+
29+
def test_empty_query_string(client):
30+
r = client.get("/diagram.png")
31+
assert r.status_code == 400
32+
33+
34+
def test_empty_dot_parameter(client):
35+
r = client.get("/diagram.png?dot=")
36+
assert r.status_code == 400
37+
38+
39+
def test_bad_dot_parameter(client):
40+
r = client.get("/diagram.png?dot=digraph")
41+
assert r.status_code == 400
42+
43+
44+
def test_good_dot_parameter(client):
45+
r = client.get("/diagram.png?dot=digraph G { A -> {B, C, D} -> {F} }")
46+
assert r.content_type == "image/png"

‎run/system-package/requirements.txt

Copy file name to clipboard
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Flask==1.1.1
2+
pytest==5.1.3
3+
gunicorn==19.9.0

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.