Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8415454

Browse files
ericschmidtatworkTakashi Matsuo
andauthored
Memorystore: Add Dockerfile for Cloud Run deployment (GoogleCloudPlatform#4191)
* Add .gcloudignore and Dockerfile for Cloud Run deployment * memorystore/redis: Add e2e test for Cloud Run * memorystore/redis: Update CR e2e test to create VPC network * Update gcloud SDK in kokoro Dockerfile to 304.0.0 Co-authored-by: Takashi Matsuo <[email protected]>
1 parent a323c06 commit 8415454

File tree

6 files changed

+329
-2
lines changed

6 files changed

+329
-2
lines changed

.kokoro/docker/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ RUN rm /tmp/get-pip.py
148148
RUN pip install --no-cache-dir virtualenv
149149

150150
# Setup Cloud SDK
151-
ENV CLOUD_SDK_VERSION 293.0.0
151+
ENV CLOUD_SDK_VERSION 304.0.0
152152
# Use system python for cloud sdk.
153153
ENV CLOUDSDK_PYTHON python3.6
154154
RUN wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-$CLOUD_SDK_VERSION-linux-x86_64.tar.gz

memorystore/redis/.gcloudignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cloud_run_deployment/
2+
gae_flex_deployment/
3+
gae_standard_deployment/
4+
gae_standard_py2_deployment/
5+
gce_deployment/
6+
gke_deployment/
7+
README.md
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Use the official lightweight Python image.
2+
# https://hub.docker.com/_/python
3+
FROM python:3.7-slim
4+
5+
# Copy local code to the container image.
6+
ENV APP_HOME /app
7+
WORKDIR $APP_HOME
8+
COPY . ./
9+
10+
# Install production dependencies.
11+
RUN pip install -r requirements.txt
12+
13+
# Run the web service on container startup. Here we use the gunicorn
14+
# webserver, with one worker process and 8 threads.
15+
# For environments with multiple CPU cores, increase the number of workers
16+
# to be equal to the cores available.
17+
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# Copyright 2020 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+
# This test creates a Memorystore instance, Serverless VPC Access
16+
# connector, and Cloud Run service and tests that the Cloud Run
17+
# service can reach the Memorystore instance.
18+
19+
import os
20+
import re
21+
import subprocess
22+
from urllib import request
23+
import uuid
24+
25+
import pytest
26+
27+
28+
@pytest.fixture()
29+
def services():
30+
# Unique suffix to create distinct service names
31+
suffix = uuid.uuid4().hex[:10]
32+
project = os.environ["GOOGLE_CLOUD_PROJECT"]
33+
34+
# Create a VPC network
35+
network_name = f"test-network-{suffix}"
36+
subprocess.run(
37+
[
38+
"gcloud",
39+
"compute",
40+
"networks",
41+
"create",
42+
network_name,
43+
"--project",
44+
project,
45+
], check=True
46+
)
47+
48+
# Create a Serverless VPC Access connector
49+
connector_name = f"test-connector-{suffix}"
50+
subprocess.run(
51+
[
52+
"gcloud",
53+
"compute",
54+
"networks",
55+
"vpc-access",
56+
"connectors",
57+
"create",
58+
connector_name,
59+
"--network",
60+
network_name,
61+
"--region=us-central1",
62+
"--range=192.168.16.0/28",
63+
"--project",
64+
project,
65+
], check=True
66+
)
67+
68+
# Create a Memorystore Redis instance
69+
instance_name = f"test-instance-{suffix}"
70+
subprocess.run(
71+
[
72+
"gcloud",
73+
"redis",
74+
"instances",
75+
"create",
76+
instance_name,
77+
"--region=us-central1",
78+
"--network",
79+
network_name,
80+
"--project",
81+
project,
82+
], check=True
83+
)
84+
85+
# Get the Redis instance's IP
86+
redis_host = subprocess.run(
87+
[
88+
"gcloud",
89+
"redis",
90+
"instances",
91+
"describe",
92+
instance_name,
93+
"--region=us-central1",
94+
"--format=value(host)",
95+
"--project",
96+
project,
97+
],
98+
stdout=subprocess.PIPE,
99+
check=True
100+
).stdout.strip().decode()
101+
102+
# Build container image for Cloud Run deployment
103+
image_name = f"gcr.io/{project}/test-visit-count-{suffix}"
104+
subprocess.run(
105+
[
106+
"cp",
107+
"cloud_run_deployment/Dockerfile",
108+
".",
109+
], check=True
110+
)
111+
subprocess.run(
112+
[
113+
"gcloud",
114+
"builds",
115+
"submit",
116+
"--tag",
117+
image_name,
118+
"--project",
119+
project,
120+
], check=True
121+
)
122+
subprocess.run(["rm", "Dockerfile"], check=True)
123+
124+
# Deploy image to Cloud Run
125+
service_name = f"test-visit-count-{suffix}"
126+
subprocess.run(
127+
[
128+
"gcloud",
129+
"run",
130+
"deploy",
131+
service_name,
132+
"--image",
133+
image_name,
134+
"--platform=managed",
135+
"--no-allow-unauthenticated",
136+
"--region=us-central1",
137+
"--vpc-connector",
138+
connector_name,
139+
"--set-env-vars",
140+
f"REDISHOST={redis_host},REDISPORT=6379",
141+
"--project",
142+
project,
143+
], check=True
144+
)
145+
146+
# Get Cloud Run service URL and auth token
147+
service_url = subprocess.run(
148+
[
149+
"gcloud",
150+
"run",
151+
"services",
152+
"describe",
153+
service_name,
154+
"--platform=managed",
155+
"--region=us-central1",
156+
"--format=value(status.url)",
157+
"--project",
158+
project,
159+
],
160+
stdout=subprocess.PIPE,
161+
check=True
162+
).stdout.strip().decode()
163+
auth_token = subprocess.run(
164+
["gcloud", "auth", "print-identity-token"],
165+
stdout=subprocess.PIPE,
166+
check=True
167+
).stdout.strip().decode()
168+
169+
yield service_url, auth_token
170+
171+
# Delete Cloud Run service
172+
subprocess.run(
173+
[
174+
"gcloud",
175+
"run",
176+
"services",
177+
"delete",
178+
service_name,
179+
"--platform=managed",
180+
"--region=us-central1",
181+
"--quiet",
182+
"--project",
183+
project,
184+
], check=True
185+
)
186+
187+
# Delete container image
188+
subprocess.run(
189+
[
190+
"gcloud",
191+
"container",
192+
"images",
193+
"delete",
194+
image_name,
195+
"--quiet",
196+
"--project",
197+
project,
198+
], check=True
199+
)
200+
201+
# Delete Redis instance
202+
subprocess.run(
203+
[
204+
"gcloud",
205+
"redis",
206+
"instances",
207+
"delete",
208+
instance_name,
209+
"--region=us-central1",
210+
"--quiet",
211+
"--async",
212+
"--project",
213+
project,
214+
], check=True
215+
)
216+
217+
# Delete Serverless VPC Access connector
218+
subprocess.run(
219+
[
220+
"gcloud",
221+
"compute",
222+
"networks",
223+
"vpc-access",
224+
"connectors",
225+
"delete",
226+
connector_name,
227+
"--region=us-central1",
228+
"--quiet",
229+
"--project",
230+
project,
231+
], check=True
232+
)
233+
234+
# Delete VPC network
235+
subprocess.run(
236+
[
237+
"gcloud",
238+
"compute",
239+
"networks",
240+
"delete",
241+
network_name,
242+
"--quiet",
243+
"--project",
244+
project,
245+
], check=True
246+
)
247+
248+
249+
def test_end_to_end(services):
250+
service_url, auth_token = services
251+
252+
req = request.Request(
253+
service_url,
254+
headers={
255+
"Authorization": f"Bearer {auth_token}"
256+
}
257+
)
258+
259+
response = request.urlopen(req)
260+
assert response.status == 200
261+
262+
body = response.read().decode()
263+
assert re.search(r"Visitor number: \d+", body) is not None

memorystore/redis/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def server_error(e):
4141

4242
if __name__ == '__main__':
4343
# This is used when running locally. Gunicorn is used to run the
44-
# application on Google App Engine. See entrypoint in app.yaml.
44+
# application on Google App Engine and Cloud Run.
45+
# See entrypoint in app.yaml or Dockerfile.
4546
app.run(host='127.0.0.1', port=8080, debug=True)
4647
# [END memorystore_main_py]

memorystore/redis/noxfile_config.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2020 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+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
26+
# We only run the cloud run tests in py38 session.
27+
'ignored_versions': ["2.7", "3.6", "3.7"],
28+
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
'gcloud_project_env': 'GOOGLE_CLOUD_PROJECT',
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
36+
# A dictionary you want to inject into your test. Don't put any
37+
# secrets here. These values will override predefined values.
38+
'envs': {},
39+
}

0 commit comments

Comments
 (0)