Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Commit 7e78cec

Browse files
committed
engelke review fixes
Change-Id: I027093776bce1958279bc66b097c03a5af1d7988
1 parent 12bc85b commit 7e78cec

25 files changed

Lines changed: 49 additions & 700 deletions

File tree

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Use of Google Cloud Platform (GCP) products & APIs is not free. While you may no
2121

2222
It's important to note that for App Engine (Standard), Python 2 is only supported as a first-generation ("Gen1") runtime whereas Python3 is only supported as a second-generation ("Gen2") runtime. This means that porting application from Python 2 to 3 also means migrating from Gen1 to Gen2 where things are different.
2323

24-
The most notable changes for developers are that bundled App Engine built-in services are absent from Gen2. The Gen1 bundled services have "grown-up" to become standalone products or have been deprecated. Gen2 also expects web apps to perform their own routing.
24+
The most notable changes for developers are that bundled App Engine built-in services are absent from Gen2. The Gen1 bundled services have "grown-up" to become standalone products or have been deprecated. Gen2 also expects web apps to perform their own application (not network) routing.
2525

2626
> **NOTE:** App Engine ([Flexible](https://cloud.google.com/appengine/docs/flexible/python/runtime?hl=en#interpreter)) is a Gen2 service but is not within the scope of these tutorials. Developers who curious can compare App Engine [Standard vs. Flexible](https://cloud.google.com/appengine/docs/the-appengine-environments).
2727
@@ -33,7 +33,7 @@ The sample app does not address complexities in your apps but serves as a guide
3333

3434
> **NOTE:**
3535
> 1. It is also possible your app does not have a user interface, i.e., mobile backends, etc., so migrating the web framework (step 1) can be skipped.
36-
> 1. Users interested in bringing back their dead apps that originally ran on the [deprecated Python 2.5 runtime](http://googleappengine.blogspot.com/2013/03/python-25-thanks-for-good-times.html) (shutdown in 2017) need to [migrate from `db` to `ndb`](http://cloud.google.com/appengine/docs/standard/python/ndb/db_to_ndb) before attempting this tutorial.
36+
> 1. Users interested in bringing back their dead apps that originally ran on the [deprecated Python 2.5 runtime](http://googleappengine.blogspot.com/2013/03/python-25-thanks-for-good-times.html) (shutdown in 2017) need to [migrate from `db` to `ndb`](http://cloud.google.com/appengine/docs/standard/python/ndb/db_to_ndb) before attempting the techniques shown in this tutorial.
3737
3838
As mentioned above, some steps are more critical while others are *optional*. We recommend incremental updates. We designed each step to be relatively easy, so you experience each migration individually. However, there are some of you for whom the migration process may be easier where you may be able to take larger migration leaps.
3939

@@ -44,18 +44,21 @@ We suggest considering where you want to end up eventually, playing with each mi
4444
Each of the migration steps have their own codelabs & corresponding overview videos:
4545

4646
1. Migrate from `webapp2` to Flask
47-
- Recommended if you have a web UI
47+
- Stongly recommended if you have a web UI
4848
- You can use another web framework as long as it supports routing
4949
1. Migrate from App Engine NDB to Cloud NDB
5050
- Stongly recommended
5151
- Can migrate from Python 2 to 3 after this step
5252
- Can migrate directly to Cloud Run after this step (see Step "2a" below)
5353
- Remaining datastore migration steps optional
5454
1. Migrate from Cloud NDB to Cloud Datastore
55-
- Recommended if you have non-App Engine code accessing Cloud Datastore
55+
- Cloud NDB works on both Python 2 & 3 App Engine runtimes (old & new), so it is optional
56+
- Recommended if already using Cloud Datastore in other (App Engine *and* non-App Engine) apps & want a consistent/reusable codebase plus reduce maintenance costs
57+
- If all you have are App Engine apps using Cloud NDB, there's no need to do this migration
5658
1. Migrate from Cloud Datastore to (native) Cloud Firestore
57-
- Recommended if you have mobile apps using Firebase+Cloud Firestore
59+
- If your app (Cloud project) uses Datastore, you cannot use Firestore.
5860
- Requires new project as Cloud Datastore & Cloud Firestore mutually-exclusive
61+
- Most developers will NOT do this migration unless you *must have* Firestore's Firebase features
5962
1. Migrate from App Engine to Cloud Run (using Cloud Datastore)
6063
- Migrate your app to a container with Docker
6164
- Alternative container migration with Buildpacks (see Step "5a" below)

step1-flask-gaendb-py2/README.md

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -202,81 +202,6 @@ AFTER:
202202

203203
---
204204

205-
## Summary
206-
207-
For the sample app in this tutorial, the overall contextual set of `diff`s look like this:
208-
209-
$ diff -c step[01]*
210-
Only in step1-flask-gaendb-py2: README.md
211-
Only in step1-flask-gaendb-py2: appengine_config.py
212-
Only in step0-webapp2-gaendb-py2: index.html
213-
diff -c step0-webapp2-gaendb-py2/main.py step1-flask-gaendb-py2/main.py
214-
*** step0-webapp2-gaendb-py2/main.py 2020-07-29 13:56:27.000000000 -0700
215-
--- step1-flask-gaendb-py2/main.py 2020-07-25 13:58:18.000000000 -0700
216-
***************
217-
*** 1,7 ****
218-
! import os
219-
! import webapp2
220-
from google.appengine.ext import ndb
221-
! from google.appengine.ext.webapp import template
222-
223-
class Visit(ndb.Model):
224-
visitor = ndb.StringProperty()
225-
--- 1,7 ----
226-
! from flask import Flask, render_template, request
227-
from google.appengine.ext import ndb
228-
!
229-
! app = Flask(__name__)
230-
231-
class Visit(ndb.Model):
232-
visitor = ndb.StringProperty()
233-
***************
234-
*** 14,26 ****
235-
return (v.to_dict() for v in Visit.query().order(
236-
-Visit.timestamp).fetch_page(limit)[0])
237-
238-
! class MainHandler(webapp2.RequestHandler):
239-
! def get(self):
240-
! store_visit(self.request.remote_addr, self.request.user_agent)
241-
! visits = fetch_visits(10) or () # empty sequence if None
242-
! tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
243-
! self.response.out.write(template.render(tmpl, {'visits': visits}))
244-
!
245-
! app = webapp2.WSGIApplication([
246-
! ('/', MainHandler),
247-
! ], debug=True)
248-
--- 14,21 ----
249-
return (v.to_dict() for v in Visit.query().order(
250-
-Visit.timestamp).fetch_page(limit)[0])
251-
252-
! @app.route('/')
253-
! def root():
254-
! store_visit(request.remote_addr, request.user_agent)
255-
! visits = fetch_visits(10) or () # empty sequence if None
256-
! return render_template('index.html', visits=visits)
257-
Only in step1-flask-gaendb-py2: requirements.txt
258-
Only in step1-flask-gaendb-py2: templates
259-
260-
The `diff` for the index HTML file isn't shown above as it changed folders, but here is an explcit contextual `diff`:
261-
262-
$ diff -c step0*/index.html step1*/templates/index.html
263-
*** step0-webapp2-gaendb-py2/index.html 2020-08-05 00:12:42.000000000 -0700
264-
--- step1-flask-gaendb-py2/templates/index.html 2020-08-05 00:13:06.000000000 -0700
265-
***************
266-
*** 8,14 ****
267-
<h3>Last 10 visits</h3>
268-
<ul>
269-
{% for visit in visits %}
270-
! <li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
271-
{% endfor %}
272-
</ul>
273-
274-
--- 8,14 ----
275-
<h3>Last 10 visits</h3>
276-
<ul>
277-
{% for visit in visits %}
278-
! <li>{{ visit.timestamp.ctime() }} from {{ visit.visitor }}</li>
279-
{% endfor %}
280-
</ul>
205+
## Next
281206

282207
In the next step, we will migrate from App Engine NDB to Google Cloud NDB, a key step because after you complete *that*, you can either stop there or be presented with a variety of options to choose from.

step2-flask-cloudndb-py2/README.md

Lines changed: 2 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ App Engine services have blossomed into their own products, and App Engine's Dat
1818
1. Update `requirements.txt` to include the Cloud NDB library (`google-cloud-ndb`).
1919
1. Update `app.yaml` to reference a pair of 3rd-party bundled packages: `grpcio` and `setuptools`
2020
1. Update `appengine_config.py` to use the `pkg_resources` tool (which comes with `setuptools`) so App Engine can access [3rd-party libraries already available on Google servers](https://cloud.google.com/appengine/docs/standard/python/tools/built-in-libraries-27) so users don't have to list them in `requirements.txt` nor `pip install` them.
21+
1. Similarly, [gRPC](http://grpc.io) is used by all [*Google Cloud* client libraries](https://cloud.google.com/apis/docs/cloud-client-libraries), and `grpcio` is the gRPC package for Python and thus required.
2122
1. Switch application code to use the Cloud NDB client library
2223

2324
### Configuration
@@ -155,95 +156,7 @@ def fetch_visits(limit):
155156

156157
---
157158

158-
## Summary
159-
160-
For this migration step, here are the contextual `diff`s:
161-
162-
$ diff -c step[12]*py2
163-
diff -c step1-flask-gaendb-py2/app.yaml step2-flask-cloudndb-py2/app.yaml
164-
*** step1-flask-gaendb-py2/app.yaml 2020-07-25 14:10:53.000000000 -0700
165-
--- step2-flask-cloudndb-py2/app.yaml 2020-08-05 00:09:42.000000000 -0700
166-
***************
167-
*** 5,7 ****
168-
--- 5,13 ----
169-
handlers:
170-
- url: /.*
171-
script: main.app
172-
+
173-
+ libraries:
174-
+ - name: grpcio
175-
+ version: 1.0.0
176-
+ - name: setuptools
177-
+ version: 36.6.0
178-
diff -c step1-flask-gaendb-py2/appengine_config.py step2-flask-cloudndb-py2/appengine_config.py
179-
*** step1-flask-gaendb-py2/appengine_config.py 2020-07-24 23:09:45.000000000 -0700
180-
--- step2-flask-cloudndb-py2/appengine_config.py 2020-07-24 22:50:57.000000000 -0700
181-
***************
182-
*** 1,6 ****
183-
--- 1,9 ----
184-
+ import pkg_resources
185-
from google.appengine.ext import vendor
186-
187-
# Set PATH to your libraries folder.
188-
PATH = 'lib'
189-
# Add libraries installed in the PATH folder.
190-
vendor.add(PATH)
191-
+ # Add libraries to pkg_resources working set to find the distribution.
192-
+ pkg_resources.working_set.add_entry(PATH)
193-
diff -c step1-flask-gaendb-py2/main.py step2-flask-cloudndb-py2/main.py
194-
*** step1-flask-gaendb-py2/main.py 2020-07-25 13:58:18.000000000 -0700
195-
--- step2-flask-cloudndb-py2/main.py 2020-07-25 14:00:56.000000000 -0700
196-
***************
197-
*** 1,18 ****
198-
from flask import Flask, render_template, request
199-
! from google.appengine.ext import ndb
200-
201-
app = Flask(__name__)
202-
203-
class Visit(ndb.Model):
204-
visitor = ndb.StringProperty()
205-
timestamp = ndb.DateTimeProperty(auto_now_add=True)
206-
207-
def store_visit(remote_addr, user_agent):
208-
! Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
209-
210-
def fetch_visits(limit):
211-
! return (v.to_dict() for v in Visit.query().order(
212-
! -Visit.timestamp).fetch_page(limit)[0])
213-
214-
@app.route('/')
215-
def root():
216-
--- 1,21 ----
217-
from flask import Flask, render_template, request
218-
! from google.cloud import ndb
219-
220-
app = Flask(__name__)
221-
+ ds_client = ndb.Client()
222-
223-
class Visit(ndb.Model):
224-
visitor = ndb.StringProperty()
225-
timestamp = ndb.DateTimeProperty(auto_now_add=True)
226-
227-
def store_visit(remote_addr, user_agent):
228-
! with ds_client.context():
229-
! Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
230-
231-
def fetch_visits(limit):
232-
! with ds_client.context():
233-
! return (v.to_dict() for v in Visit.query().order(
234-
! -Visit.timestamp).fetch_page(limit)[0])
235-
236-
@app.route('/')
237-
def root():
238-
diff -c step1-flask-gaendb-py2/requirements.txt step2-flask-cloudndb-py2/requirements.txt
239-
*** step1-flask-gaendb-py2/requirements.txt 2020-07-24 19:27:45.000000000 -0700
240-
--- step2-flask-cloudndb-py2/requirements.txt 2020-07-24 21:59:58.000000000 -0700
241-
***************
242-
*** 1 ****
243-
--- 1,2 ----
244-
Flask
245-
+ google-cloud-ndb
246-
Common subdirectories: step1-flask-gaendb-py2/templates and step2-flask-cloudndb-py2/templates
159+
## Next
247160

248161
From here, you have some flexibility as to your next move. You can...
249162

step2-flask-cloudndb-py3/README.md

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Introduction
44

5-
We recommend developers migrate to Python 3 to access the latest App Engine runtimes & features. Developers can make this migration as soon as they've migrated to Cloud NDB (now). However since this is a large undertaking, you can move to Py3 after any of the datastore migration steps, not just this one. One of the outstanding features of the App Engine second generation runtimes (Gen2) is that neither "vendored" nor bundled 3rd-party packages are required to be uploaded to the service. They are automatically installed directly from `requirements.txt`.
5+
We recommend developers migrate to Python 3 to access the latest App Engine runtimes & features. Developers can make this migration as soon as they've migrated to Cloud NDB (now). However since this can be a large undertaking, you can move to Py3 after any of the datastore migration steps, not just this one. One of the outstanding features of the App Engine second generation runtimes (Gen2) is that neither "vendored" nor bundled 3rd-party packages are required to be uploaded to the service. They are automatically installed directly from `requirements.txt`.
66

77
---
88

@@ -31,37 +31,7 @@ handlers:
3131

3232
---
3333

34-
## Summary
35-
36-
For the sample app in this tutorial, the overall contextual set of `diff`s (skipping this `README.md` and nonessential files) looks like this:
37-
38-
$ diff -c step2-flask-cloudndb-py?
39-
diff -c step2-flask-cloudndb-py2/app.yaml step2-flask-cloudndb-py3/app.yaml
40-
*** step2-flask-cloudndb-py2/app.yaml 2020-08-05 00:09:42.000000000 -0700
41-
--- step2-flask-cloudndb-py3/app.yaml 2020-07-24 23:59:03.000000000 -0700
42-
***************
43-
*** 1,13 ****
44-
! runtime: python27
45-
! threadsafe: yes
46-
! api_version: 1
47-
48-
handlers:
49-
- url: /.*
50-
! script: main.app
51-
!
52-
! libraries:
53-
! - name: grpcio
54-
! version: 1.0.0
55-
! - name: setuptools
56-
! version: 36.6.0
57-
--- 1,5 ----
58-
! runtime: python38
59-
60-
handlers:
61-
- url: /.*
62-
! script: auto
63-
Only in step2-flask-cloudndb-py2: appengine_config.py
64-
Common subdirectories: step2-flask-cloudndb-py2/templates and step2-flask-cloudndb-py3/templates
34+
## Next
6535

6636
From here, your options are:
6737

step2a-flask-cloudndb-py2-cloudrun/README.md

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,36 +42,7 @@ if __name__ == '__main__':
4242

4343
---
4444

45-
## Summary
46-
47-
For the sample app in this tutorial, the overall contextual set of `diff`s (skipping this `README.md` and nonessential files) looks like this:
48-
49-
$ diff -c step2*py2*
50-
Only in step2a-flask-cloudndb-py2-cloudrun: .dockerignore
51-
Only in step2a-flask-cloudndb-py2-cloudrun: Dockerfile
52-
Only in step2-flask-cloudndb-py2: app.yaml
53-
Only in step2-flask-cloudndb-py2: appengine_config.py
54-
diff -c step2-flask-cloudndb-py2/main.py step2a-flask-cloudndb-py2-cloudrun/main.py
55-
*** step2-flask-cloudndb-py2/main.py 2020-07-25 14:00:56.000000000 -0700
56-
--- step2a-flask-cloudndb-py2-cloudrun/main.py 2020-08-11 19:17:15.000000000 -0700
57-
***************
58-
*** 1,3 ****
59-
--- 1,4 ----
60-
+ import os
61-
from flask import Flask, render_template, request
62-
from google.cloud import ndb
63-
64-
***************
65-
*** 22,24 ****
66-
--- 23,29 ----
67-
store_visit(request.remote_addr, request.user_agent)
68-
visits = fetch_visits(10) or () # empty sequence if None
69-
return render_template('index.html', visits=visits)
70-
+
71-
+ if __name__ == '__main__':
72-
+ app.run(debug=True, threaded=True, host='0.0.0.0',
73-
+ port=int(os.environ.get('PORT', 8080)))
74-
Common subdirectories: step2-flask-cloudndb-py2/templates and step2a-flask-cloudndb-py2-cloudrun/templates
45+
## Next
7546

7647
From here, you have some flexibility as to your next move. You can...
7748

0 commit comments

Comments
 (0)