<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abby Carey</title>
    <description>The latest articles on DEV Community by Abby Carey (@abbyapplebees).</description>
    <link>https://dev.to/abbyapplebees</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F284260%2F14896e59-26ca-4c04-a693-2150311c30ba.jpg</url>
      <title>DEV Community: Abby Carey</title>
      <link>https://dev.to/abbyapplebees</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abbyapplebees"/>
    <language>en</language>
    <item>
      <title>Getting serverless with Python and Cloud Run</title>
      <dc:creator>Abby Carey</dc:creator>
      <pubDate>Fri, 02 Oct 2020 19:09:05 +0000</pubDate>
      <link>https://dev.to/googlecloud/getting-serverless-with-python-and-cloud-run-53b5</link>
      <guid>https://dev.to/googlecloud/getting-serverless-with-python-and-cloud-run-53b5</guid>
      <description>&lt;p&gt;On this edition of Serverless Expeditions, we take a look at how to deploy a Cloud Run service written in Python.&lt;/p&gt;

&lt;p&gt;Check out the video version of this blog post.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/s2TIWIzCftM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Source code for this blog post is available on GitHub.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/GoogleCloudPlatform" rel="noopener noreferrer"&gt;
        GoogleCloudPlatform
      &lt;/a&gt; / &lt;a href="https://github.com/GoogleCloudPlatform/serverless-expeditions" rel="noopener noreferrer"&gt;
        serverless-expeditions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Managing the resources for an app can be a challenge. Deploying your app in a serverless fashion is popular because it helps take care of that for you. &lt;a href="https://cloud.google.com/run" rel="noopener noreferrer"&gt;Cloud Run&lt;/a&gt; is fully managed, meaning you don’t have to worry about infrastructure scaling as traffic changes. Since it’s container based, you can also use any language and framework. An added bonus is that you can redeploy with just one command.&lt;/p&gt;

&lt;p&gt;Let’s say you and your friends are planning a foreign wine night. Most of the shops your group want to order from are in the EU and family owned. Their online stores don't display your country's currency (USD). &lt;/p&gt;

&lt;p&gt;To get an accurate gauge on price, a unit conversion service that converts Euros to USD can be made and deployed to Cloud Run with &lt;a href="https://flask.palletsprojects.com/en/1.1.x/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt;. Flask is a popular framework for creating Python web apps because it’s lightweight and easy to set up.&lt;/p&gt;

&lt;p&gt;Your Cloud Run service has the basics: &lt;/p&gt;

&lt;p&gt;An html file where a form gets user input.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;A simple css file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And an app.py file where functions and routes are defined.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For the full source of this project, check out our &lt;a href="https://github.com/GoogleCloudPlatform/serverless-expeditions/tree/master/using-python-on-google-cloud-with-cloud-run" rel="noopener noreferrer"&gt;repository on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you’ve created your service, Cloud Run only needs one extra file for deployment. No code changes needed.&lt;/p&gt;

&lt;p&gt;This is the Docker file. Here you customize the runtime of your container to suit your needs exactly. Containers are a way to isolate your service to make it run the same no matter where it’s deployed.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Taking a closer look…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FROM&lt;/code&gt; specifies a base Docker image, the Python runtime.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COPY&lt;/code&gt; adds files from your computer's current directory to a directory inside the container.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RUN&lt;/code&gt; installs Flask ,&lt;a href="https://docs.gunicorn.org/en/stable/" rel="noopener noreferrer"&gt;Gunicorn&lt;/a&gt;, and our currency converter's dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt; is a command that starts your app inside the container and binds it to a port. App:app means import the app from the app.py file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to run a different version of Python, it’s no big deal. With Cloud Run you can run any version of Python you want as long as there’s a &lt;a href="https://hub.docker.com/_/python" rel="noopener noreferrer"&gt;Python base docker image&lt;/a&gt; available for it.&lt;/p&gt;

&lt;p&gt;With Docker file in hand, you can now kick off your first deployment. You first build a container with Cloud Build. This bundles up your code along with everything you’ve added in your Docker file and pushes it to the Container Registry. Container Registry is where your container images are stored. Finally, you deploy the service to Cloud Run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx7w03ny67yubwd161pge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx7w03ny67yubwd161pge.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All this is handled with just two commands. From your terminal, run the following commands to build a container image and deploy the service using that image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gcloud builds submit --tag gcr.io/PROJECT_ID/euro-to-usd

$ gcloud run deploy --image gcr.io/PROJECT_ID/euro-to-usd
--platform managed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! Your Cloud Run service is now deployed. &lt;/p&gt;

&lt;p&gt;Going to the Cloud Run section of Google Cloud now shows your deployed service and its URL.&lt;/p&gt;

&lt;p&gt;Here you also have access to important metrics and the Revisions tab, where you can easily redirect and split traffic to different versions of service if you’ve deployed it more than once. This is handy if you discover a breaking change and want to temporarily roll back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffv9nrk7fmnxbqd8okbe6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffv9nrk7fmnxbqd8okbe6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what if your friends hit an error when trying your service out? How could you figure out what’s going wrong? That’s where &lt;a href="https://cloud.google.com/monitoring" rel="noopener noreferrer"&gt;Cloud Monitoring&lt;/a&gt; comes in.&lt;/p&gt;

&lt;p&gt;Cloud Run has a Logs tab where you can see everything being logged by your service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fupnp3hmw2igal4b2wuov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fupnp3hmw2igal4b2wuov.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To dig a little deeper, there’s &lt;a href="https://cloud.google.com/error-reporting" rel="noopener noreferrer"&gt;Error Reporting&lt;/a&gt;. Here we see a value error was triggered on line 20.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4xi00yi1nkmcvwh6kprl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4xi00yi1nkmcvwh6kprl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After taking a look at the stack trace, making a quick fix, and redeploying, you now have a working app to share. Goodbye Euros, hello USD!&lt;/p&gt;

&lt;p&gt;Now, with correctly calculated wine prices, the whole group is ready to buy fancy wine that fits their budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Serverless Expeditions
&lt;/h2&gt;

&lt;p&gt;Serverless Expeditions is a fun and cheeky video series that looks at what serverless means and how to build serverless apps with Google Cloud. &lt;br&gt;
Follow these hosts on Twitter at &lt;a href="https://twitter.com/abbyapplebees" rel="noopener noreferrer"&gt;@abbyapplebees&lt;/a&gt; and &lt;a href="https://twitter.com/martinomander" rel="noopener noreferrer"&gt;@martinomander&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>serverlessexpeditions</category>
      <category>python</category>
    </item>
    <item>
      <title>Creating a cloud-based Pokédex: Local testing with Cloud SQL Proxy</title>
      <dc:creator>Abby Carey</dc:creator>
      <pubDate>Thu, 09 Jul 2020 15:56:07 +0000</pubDate>
      <link>https://dev.to/abbyapplebees/creating-a-cloud-based-pokedex-local-testing-with-cloud-sql-proxy-5hb2</link>
      <guid>https://dev.to/abbyapplebees/creating-a-cloud-based-pokedex-local-testing-with-cloud-sql-proxy-5hb2</guid>
      <description>&lt;p&gt;Previously in this series, I went over &lt;a href="https://dev.to/googlecloud/creating-a-cloud-based-pokedex-overview-o8j"&gt;what I used to build my first Python web app&lt;/a&gt;. In this post, we're taking a look at how to locally test a Flask app with &lt;a href="https://cloud.google.com/sql/docs/mysql/sql-proxy"&gt;Cloud SQL Proxy&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Locally testing a Flask app that's connected to a Cloud SQL instance can be a little tricky. It's not as simple as calling &lt;code&gt;python3 main.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an example, let's walk through creating a Cloud SQL instance and testing my Pokédex project locally.&lt;/p&gt;

&lt;p&gt;Clone my repo to get started.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/abbycar"&gt;
        abbycar
      &lt;/a&gt; / &lt;a href="https://github.com/abbycar/pokedex-project"&gt;
        pokedex-project
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  A look at Cloud SQL Proxy
&lt;/h3&gt;

&lt;p&gt;Cloud SQL Proxy allows you to locally communicate securely with your Cloud SQL instance.&lt;/p&gt;

&lt;p&gt;The proxy handles data encryption to and from your database using Transport Layer Security (TLS). If you're not familiar with TLS, you can see it in action as the padlock in your address bar. SSL certificates establish authority, verifying client and server identities.&lt;/p&gt;

&lt;p&gt;It also handles authentication with Cloud SQL, removing the need to provide static IP addresses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t39xUAP6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cloud.google.com/sql/images/proxyconnection.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t39xUAP6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cloud.google.com/sql/images/proxyconnection.svg" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you eventually deploy your app to App Engine, your app uses the Cloud SQL Proxy that’s built in to the App Engine environment.  &lt;/p&gt;

&lt;p&gt;When testing things locally, you need to download your own copy of the Cloud SQL Proxy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Google Cloud products
&lt;/h3&gt;

&lt;p&gt;Since this app uses Google Cloud Platform (GCP) products, we need to create a GCP project.&lt;/p&gt;

&lt;p&gt;Get access to GCP by &lt;a href="https://console.cloud.google.com/projectselector/appengine/create"&gt;creating a new project&lt;/a&gt; with &lt;a href="https://cloud.google.com/billing/docs/how-to/modify-project#confirm_billing_is_enabled_on_a_project"&gt;billing enabled&lt;/a&gt;. If this is your first time trying out GCP, you can start a &lt;a href="https://cloud.google.com/free/"&gt;free trial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You also need to install the &lt;a href="https://cloud.google.com/sdk/docs/"&gt;Google Cloud SDK&lt;/a&gt; and enable the following APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://console.cloud.google.com/apis/library/sql-component.googleapis.com"&gt;Cloud SQL API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://console.cloud.google.com/apis/library/storage-component.googleapis.com"&gt;Cloud Storage API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you’ve done all that, open a terminal and enter the following command to get credentials for authenticating with GCP services.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ gcloud auth application-default login&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a MySQL Cloud SQL instance
&lt;/h3&gt;

&lt;p&gt;Let’s start by creating a second generation MySQL instance in your terminal. &lt;/p&gt;

&lt;p&gt;The following command takes a few minutes to complete. Check up on the creation status at the &lt;a href="https://console.cloud.google.com/sql/instances"&gt;instances page&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud sql instances create &amp;lt;MY-INSTANCE&amp;gt; &lt;span class="nt"&gt;--root-password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;ROOT_PASSWORD&amp;gt; &lt;span class="nt"&gt;--database-version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MYSQL_5_7 &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-central
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now that you have an instance, add a new database named &lt;code&gt;pokemon&lt;/code&gt;. This is where we store all pokemon and user info.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud sql databases create pokemon &lt;span class="nt"&gt;--instance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;MY-INSTANCE&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Your new database now shows up in your Cloud SQL instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oCq4Wtf_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/frqbxrn9ewfazolivq3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oCq4Wtf_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/frqbxrn9ewfazolivq3a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can connect to your database with your root user account and password. Optionally, create a new user. A host set to % means the user has an unrestricted host name.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gcloud sql &lt;span class="nb"&gt;users &lt;/span&gt;create USERNAME &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;% &lt;span class="nt"&gt;--instance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;MY-INSTANCE&amp;gt; &lt;span class="nt"&gt;--password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;PASSWORD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Connect to your database with Cloud SQL Proxy
&lt;/h3&gt;

&lt;p&gt;Open a terminal at the sample code folder and download an executable Cloud SQL Proxy with the following commands. For non-linux commands, check out the Cloud SQL Proxy quickstart.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 &lt;span class="nt"&gt;-O&lt;/span&gt; cloud_sql_proxy&lt;span class="sb"&gt;`&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x cloud_sql_proxy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Run the proxy and connect to your instance. You can find your instance connection name &lt;a href="https://console.cloud.google.com/sql/instances/my-instance/overview"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./cloud_sql_proxy -instances=&amp;lt;INSTANCE_CONNECTION_NAME&amp;gt;=tcp:3306&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keep the Cloud SQL Proxy running in the current terminal and continue along in a new one. Without this connection, the app won’t be able to retrieve data from the pokemon database.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure your environment
&lt;/h3&gt;

&lt;p&gt;For local testing, update your config.py. It’s best to store these variables as environment variables in app.yaml, however, app.yaml variables aren’t reflected until deploying to App Engine. I’ll go over app.yaml and the deployment process later in this series.&lt;/p&gt;

&lt;p&gt;A hot new product Google Cloud added recently is &lt;a href="https://cloud.google.com/secret-manager"&gt;Secret Manager&lt;/a&gt;. You should check it out if you want to store sensitive info in the cloud instead of in a file in your code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a virtual environment
&lt;/h3&gt;

&lt;p&gt;Since the Python packages and modules you’ve installed probably aren’t the same as what my app needs, a virtual environment gives my app the perfect place to run. &lt;/p&gt;

&lt;p&gt;To get one up and running, enter the &lt;code&gt;virtualenv&lt;/code&gt; command and activate it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;virtualenv &lt;span class="nt"&gt;-p&lt;/span&gt; python3 venv
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should now see &lt;code&gt;(venv)&lt;/code&gt; next to your file path in the terminal.&lt;br&gt;
Now install the necessary packages and modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Load MySQL data with a .csv
&lt;/h3&gt;

&lt;p&gt;Since the database is currently empty, testing my app now will fail.&lt;/p&gt;

&lt;p&gt;In my repo I have all pokemon data stored in the &lt;a href="https://github.com/abbycar/pokedex-project/blob/master/pokemon-db.csv"&gt;pokemon-db.csv file&lt;/a&gt;. Use this to initially populate the database.&lt;/p&gt;

&lt;p&gt;Call the following command to create your relational tables. At this point they’ll be empty and ready for some data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 pokeview/models.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a new terminal, connect to your MySQL instance and load the provided pokemon-db.csv file. &lt;strong&gt;Your Cloud SQL Proxy must be running in a different terminal for this to work&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mysql -u username -p --host 127.0.0.1 

LOAD DATA LOCAL INFILE 'pokemon-db.csv' INTO TABLE pokedex FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n' IGNORE 1 LINES
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After loading the CSV, your pokedex table should now have the original 151 pokemon in it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it!
&lt;/h3&gt;

&lt;p&gt;It’s time for all that setup work to pay off!&lt;br&gt;
Run your app to start up a local webserver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 main.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In your web browser, go to &lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt; where the app is running. The port is configured via the main.py file.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Getting around API timeouts with Cloud Functions and Cloud Pub/Sub</title>
      <dc:creator>Abby Carey</dc:creator>
      <pubDate>Wed, 20 May 2020 16:21:49 +0000</pubDate>
      <link>https://dev.to/googlecloud/getting-around-api-timeouts-with-cloud-functions-and-cloud-pub-sub-47o3</link>
      <guid>https://dev.to/googlecloud/getting-around-api-timeouts-with-cloud-functions-and-cloud-pub-sub-47o3</guid>
      <description>&lt;p&gt;Recently I was pitched a revolutionary Slackbot idea. What if, with the power of Cloud Functions and Cloud Vision, I could take any image and &lt;a href="https://en.wikipedia.org/wiki/Doge_(meme)" rel="noopener noreferrer"&gt;dogeify&lt;/a&gt; it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3mdm0ei781hhzi5e8ray.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3mdm0ei781hhzi5e8ray.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;em&gt;An image run through my Slackbot&lt;/em&gt;
  &lt;/p&gt;

&lt;p&gt;In this post, I'll show you how I built a Slackbot with Python that does exactly this. In addition, I'll show you how to overcome a common issue when working with APIs and how a unique Cloud Functions pattern can help you overcome this obstacle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The timeout problem
&lt;/h2&gt;

&lt;p&gt;My &lt;a href="https://api.slack.com/interactivity/slash-commands" rel="noopener noreferrer"&gt;slash command&lt;/a&gt; Slackbot consisted of one Cloud Function, doge-response. When someone types &lt;code&gt;/doge&lt;/code&gt; in their Slack client, Slack sends an HTTP event that triggers my Cloud Function with the text the user typed after my command. This text should be an image URL to dogeify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkzlo92i90uvgvyioula8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkzlo92i90uvgvyioula8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data flow looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fker1wliqi24rmuole3c0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fker1wliqi24rmuole3c0.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, when it was time for testing, my Slackbot would think about things for a bit and return an &lt;strong&gt;operation_timeout&lt;/strong&gt; error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5vuiur5omknumutb4orx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5vuiur5omknumutb4orx.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;em&gt;Ugh.&lt;/em&gt;
  &lt;/p&gt;

&lt;p&gt;Timeouts are a problem for many services. Some give you 5 seconds, some even more, but in the end it sometimes isn’t enough for what you want to do.&lt;/p&gt;

&lt;p&gt;After some research, I learned that Slack only gives you &lt;strong&gt;&lt;a href="https://api.slack.com/interactivity/slash-commands#responding_basic_receipt" rel="noopener noreferrer"&gt;three seconds&lt;/a&gt;&lt;/strong&gt; to respond to a slash command. Three seconds isn’t enough time to run a large image though Cloud Vision, create a new image, overlay Cloud Vision labels, and upload that image to Cloud Storage.&lt;/p&gt;

&lt;p&gt;How did I get around these pesky timeouts? The solution is to get asynchronous, which wasn’t as hard as I thought it would be. By sending messages between multiple Cloud Functions, I was able to avoid API timeouts entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Cloud Functions are better than one
&lt;/h2&gt;

&lt;p&gt;The first step towards an asynchronous Slackbot was to split my single Cloud Function into two. &lt;/p&gt;

&lt;p&gt;To facilitate messaging between these two functions, I tied in &lt;a href="https://cloud.google.com/pubsub/docs/" rel="noopener noreferrer"&gt;Cloud Pub/Sub&lt;/a&gt;. Cloud Pub/Sub is a real-time messaging service that allows you to send and receive messages between independent apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxu2w6a5qqwl6qz4nzfnj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxu2w6a5qqwl6qz4nzfnj.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud Function 1: doge-queue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/functions/docs/calling/http" rel="noopener noreferrer"&gt;Triggered by HTTP&lt;/a&gt; from &lt;code&gt;/doge&lt;/code&gt; slash Slack command.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verifies that the request is good&lt;/li&gt;
&lt;li&gt;Publishes the contents of the Slack response to my Cloud Pub/Sub topic, &lt;strong&gt;doge-convert&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Returns a “Working on that” message back to the Slack channel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cloud Function 2: doge-response&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/functions/docs/calling/pubsub" rel="noopener noreferrer"&gt;Triggered by Cloud Pub/Sub&lt;/a&gt; publishings to the &lt;strong&gt;doge-convert&lt;/strong&gt; topic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decodes the Cloud Pub/Sub event data and now has the contents of the Slack request&lt;/li&gt;
&lt;li&gt;Dogefies the image&lt;/li&gt;
&lt;li&gt;Sends the image back to the slack channel where it was called using the &lt;strong&gt;response_url&lt;/strong&gt; attribute of the Slack request&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the &lt;strong&gt;doge-queue&lt;/strong&gt; Cloud Function, publishing one message to Cloud Pub/Sub takes less than 3 seconds, giving me time to send a response back to the Slack channel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12ej1yh1xq8ope401l4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12ej1yh1xq8ope401l4e.png"&gt;&lt;/a&gt;&lt;br&gt;&lt;em&gt;Much better than a timeout!&lt;/em&gt;
  &lt;/p&gt;

&lt;p&gt;This message buys me &lt;strong&gt;30 minutes&lt;/strong&gt; to respond back to the Slack channel. While 30 minutes is awesome, I also need to think about other timeouts that could arise. Cloud Functions itself has a default timeout of &lt;strong&gt;one minute&lt;/strong&gt;, which is plenty of time for what I need to do. If I needed more time, I could have &lt;a href="https://cloud.google.com/functions/docs/concepts/exec#timeout" rel="noopener noreferrer"&gt;updated my Cloud Function’s timeout&lt;/a&gt; to be up to &lt;strong&gt;9 minutes&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Gettin’ Cloud Pub/Sub with it
&lt;/h2&gt;

&lt;p&gt;After setting up a my Cloud Pub/Sub &lt;strong&gt;doge-convert&lt;/strong&gt; topic and creating a &lt;a href="https://cloud.google.com/pubsub/docs/subscriber#push_pull" rel="noopener noreferrer"&gt;pull subscription&lt;/a&gt; for &lt;strong&gt;doge-response&lt;/strong&gt;, it was time to connect the dots between my two Cloud Functions.&lt;/p&gt;

&lt;p&gt;In my &lt;code&gt;doge_queue&lt;/code&gt; function, I dumped the contents of the Slack request into a JSON object.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;publisher_client.publish()&lt;/code&gt; then takes my topic path and the JSON object (encoded), publishing it to my topic.&lt;/p&gt;

&lt;p&gt;By assigning &lt;code&gt;publisher_client.publish()&lt;/code&gt; to a variable, &lt;code&gt;future&lt;/code&gt;, I can check the &lt;code&gt;future.result&lt;/code&gt; to confirm the message was published successfully.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;At this point, a message sent with my Slackbot is now in my doge-convert topic. Once that message hits the topic, doge-response is triggered by the event.&lt;/p&gt;

&lt;p&gt;In my &lt;code&gt;doge_response&lt;/code&gt; function, I grab the &lt;code&gt;data&lt;/code&gt; out of the event and decode it.&lt;/p&gt;

&lt;p&gt;With just one line of code, I now have the contents of my Slack request to work with in my second Cloud Function.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that’s it! By having my first Cloud Function send an initial message back to Slack while it publishes the contents of the Slack request to Cloud Pub/Sub, I buy my second Cloud Function plenty of time to do all the heavy lifting. Goodbye 3 second API timeout limitation!&lt;/p&gt;

&lt;p&gt;If you want to see all the code for this Slackbot, including how I handled image storage, called the Cloud Vision API, and handled text overlay, check out my GitHub repo!&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/abbycar" rel="noopener noreferrer"&gt;
        abbycar
      &lt;/a&gt; / &lt;a href="https://github.com/abbycar/doge-a-chat" rel="noopener noreferrer"&gt;
        doge-a-chat
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A Slackbot that receives an image as a slash command and returns it back in Doge meme format.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>serverless</category>
      <category>cloudfunctions</category>
      <category>cloudpubsub</category>
    </item>
    <item>
      <title>Creating a cloud-based Pokédex: overview</title>
      <dc:creator>Abby Carey</dc:creator>
      <pubDate>Tue, 28 Jan 2020 17:39:22 +0000</pubDate>
      <link>https://dev.to/googlecloud/creating-a-cloud-based-pokedex-overview-o8j</link>
      <guid>https://dev.to/googlecloud/creating-a-cloud-based-pokedex-overview-o8j</guid>
      <description>&lt;p&gt;This blog series details what I learned on my Python 3 app development journey and the roadblocks I hit along the way. In this post I give an overview of a Python 3 app I created using Flask and a variety of &lt;a href="https://cloud.google.com/products/"&gt;Google Cloud Platform (GCP)&lt;/a&gt; offerings.&lt;/p&gt;

&lt;p&gt;If you’re new to Python 3 web app development, you’ll quickly learn that you have a lot of choices to make. You might ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Is there a preferred framework?&lt;/li&gt;
&lt;li&gt;  How do I handle user authentication?&lt;/li&gt;
&lt;li&gt;  How do I show the world my app?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the same questions I asked myself. As with many questions in life, the answer is “It depends”, but you can take out the guesswork by building from a credible sample.&lt;/p&gt;

&lt;h2&gt;
  
  
  The final result
&lt;/h2&gt;

&lt;p&gt;For my first Python web app, I decided to create a simple Pokédex. It includes the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Data displayed from a &lt;a href="https://cloud.google.com/sql/"&gt;Cloud SQL&lt;/a&gt; database&lt;/li&gt;
&lt;li&gt;  User account creation and persistent sign in&lt;/li&gt;
&lt;li&gt;  A Pokédex for each user&lt;/li&gt;
&lt;li&gt;  The ability for users to toggle and store the catch status of pokémon through POST requests&lt;/li&gt;
&lt;li&gt;  Automatic scaling with &lt;a href="https://cloud.google.com/appengine/"&gt;App Engine&lt;/a&gt; once deployed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the &lt;a href="https://abbycar-test.appspot.com/"&gt;final result&lt;/a&gt; deployed to App Engine. Log in with my test account to scope things out.&lt;/p&gt;

&lt;p&gt;Username: &lt;strong&gt;test&lt;/strong&gt;&lt;br&gt;
Password: &lt;strong&gt;testtest&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s not too pretty or feature packed, but feel free to “catch” some pokémon by clicking on the pokéballs!&lt;/p&gt;

&lt;p&gt;Check out the code on GitHub&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/abbycar"&gt;
        abbycar
      &lt;/a&gt; / &lt;a href="https://github.com/abbycar/pokedex-project"&gt;
        pokedex-project
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wx69LOQN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9dx3f3pkbgtzwmkueved.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wx69LOQN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9dx3f3pkbgtzwmkueved.png" alt="pokéview app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get rolling with starter code
&lt;/h2&gt;

&lt;p&gt;Choosing what technologies you want your app to use is hard. I find learning new concepts easiest when building off existing projects. I tried a handful of tutorials that used a variety of technologies before settling.&lt;/p&gt;

&lt;p&gt;I got my bearings with the &lt;a href="https://github.com/GoogleCloudPlatform/getting-started-python/tree/828ff9106bce1177cfb5392d22f25d831b2797d4/3-binary-data"&gt;Python + MySQL bookshelf example&lt;/a&gt;. Note that since starting this project the docs and code sample have changed. You can see a snapshot of the docs I used &lt;a href="https://web.archive.org/web/20181130130303/https://cloud.google.com/python/getting-started/tutorial-app"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I chose to build off this project because it had the bones of what I wanted to do. The choice of tech was handled for me. All I had to do was trim some fat and slap a bit o’ muscle on it. A fair bit of tweaking was involved to get where I wanted to go, but in the end you’re learning from a (hopefully) credible source on what a good app looks like.  &lt;/p&gt;

&lt;p&gt;The app I created utilizes the tech listed below. Note that I’ve chosen to use Google Cloud products for this sample. AWS and Azure have similar offerings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flask and Jinja2
&lt;/h3&gt;

&lt;p&gt;When it comes to my apps, I hate boilerplate code. I want to get my app up and running without an additional 1,000 lines of code clogging things up.&lt;/p&gt;

&lt;p&gt;To limit this in my app, I picked Flask as my framework and Jinja2 as my templating engine. Both add hardly any boilerplate to my app.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://flask.palletsprojects.com/en/1.1.x/"&gt;Flask&lt;/a&gt; is a light-weight Python web framework that’s great for beginners because out of the box you get the basics of what you need. If you find yourself needing other features like user sign in and database management, just install an extension.&lt;/p&gt;

&lt;p&gt;By default, you need to install the&lt;a href="https://jinja.palletsprojects.com/en/2.10.x/"&gt; Jinja2&lt;/a&gt; template engine to use Flask.&lt;/p&gt;

&lt;p&gt;Sticking with Jinja2 was an easy choice for me since I didn’t want boilerplate code and because I didn’t choose Django as my Python web framework. &lt;/p&gt;

&lt;h4&gt;
  
  
  Why no Django?
&lt;/h4&gt;

&lt;p&gt;Django is another popular route to go, but I know that my app will stay relatively small. I don’t need all the bells and whistles it offers. Also, Django apps are usually &lt;a href="http://www.codingthearchitecture.com/2014/11/19/what_is_a_monolith.html"&gt;monolithic&lt;/a&gt; in nature.&lt;/p&gt;

&lt;p&gt;Flask puts an emphasis on &lt;a href="https://opensource.com/resources/what-are-microservices"&gt;microservice&lt;/a&gt; based architectures and modularity, making it better for beginners. While my app doesn’t have microservices, it does have &lt;a href="https://flask.palletsprojects.com/en/1.0.x/blueprints/"&gt;Blueprints&lt;/a&gt; which provide separation of operations at the application level, and share one app config.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud SQL and Cloud Storage
&lt;/h3&gt;

&lt;p&gt;I wanted all my app’s content to live in the cloud. Google Cloud in particular.&lt;/p&gt;

&lt;p&gt;Cloud SQL for MySQL is a fully-managed database service that makes it easy to create and manage MySQL relational databases instances in the &lt;a href="https://console.cloud.google.com/"&gt;Google Cloud Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It also supports secure external connections and local development with the &lt;a href="https://cloud.google.com/sql/docs/mysql/sql-proxy"&gt;Cloud SQL Proxy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cloud Storage was something I didn’t know I needed until I learned about hotlinking. Hotlinking (also known as bandwidth theft) is when you display static assets (such as images) on one website that are hosted on another website.&lt;/p&gt;

&lt;p&gt;To be respectful of others web resources, I downloaded what I needed and stored it in a Cloud Storage bucket. This gives me full control of my resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  SQLAlchemy
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zjfh51N4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n4va0f000rf1v8bscims.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zjfh51N4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/n4va0f000rf1v8bscims.png" alt="sqlalchemy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; is a database toolkit and &lt;a href="https://www.fullstackpython.com/object-relational-mappers-orms.html"&gt;object-relational mapper (ORM)&lt;/a&gt; implementation. It provides an interface for creating and executing database-agnostic code without needing to write SQL statements. For my example I chose to go with MySQL, but I could’ve picked PostgreSQL or MongoDB and used the exact same code I’ve written in my app.&lt;/p&gt;

&lt;p&gt;Not having to write SQL statements is a pro if you’re a SQL beginner. However, you do need to have a good grasp of query logic to use SQLAlchemy statements.&lt;/p&gt;

&lt;h3&gt;
  
  
  App Engine
&lt;/h3&gt;

&lt;p&gt;App Engine is one of GCP’s web hosting options. App Engine automatically handles scaling my app’s network resources up and down depending on how many requests are hitting my app.&lt;/p&gt;

&lt;p&gt;It’s a good fit if you don’t want to think about the nitty gritty of load balancing.&lt;/p&gt;

&lt;p&gt;In the end my app has the following structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HtNE7RVD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mnw4meqazvk7wmj6g2p8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HtNE7RVD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mnw4meqazvk7wmj6g2p8.png" alt="App components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned for the next part of this series. We’re going over how to locally test Flask apps with Cloud SQL Proxy.&lt;/p&gt;

</description>
      <category>flask</category>
      <category>mysql</category>
      <category>googlecloud</category>
    </item>
  </channel>
</rss>
