Hackers and Slackers

Creating Google Cloud Functions Running Python 3.7

GCP scores another victory by trivializing serverless functions

The more I explore Google Cloud's endless catalog of cloud services, the more I really like Google Cloud. This is why before moving forward, I'd like to be transparent that this blog has become little more than thinly veiled Google propaganda, where I will henceforth bombard you with persuasive and subtle messaging to sell your soul to Google. Let's be honest; they've probably simulated it anyway.

It should be safe to assume that you're fairly familiar with AWS Lambda Functions, which have served as the backbone of what we refer to as "serverless." These code snippets in the cloud have restructured entire IT departments and are partially why almost nobody knows enough basic Linux to configure a web server or build anything without a vendor. In my opinion, Google Cloud Functions are better than that, so strap in.

AWS vs GCP Workflow Comparison

AWS' architecture philosophy leans heavily towards chaining together services into what inevitably becomes a web of self-contained billable items on your invoice. A fine illustration of this is a fine post on common AWS patterns, which provides a decent visual of this complexity, while also revealing how much people apparently love this kind of shit, as though SaaS is the new Legos.

To interact with a Lambda function in AWS via HTTP requests, AWS, you need to set up an API Gateway in front. This is a feat sometimes as daunting as coding itself, followed by a user permission struggle just to get your your user the access to create Lambdas, as well as individual policies associated with *every other microservice you hope to interact with.*  

Eventually, you’ll get to write some code or upload a horrendous zip file like some sort of neanderthal (friendly reminder: I am entirely biased and actively attempting to brainwash you.)

GCP has clearly been taking notes on the sidelines on how to improve this process by removing red tape around service setup or policy configuration. AWS and GCP are tackling opposites approaches; AWS allows you to build a Robust API complete with staging and testing with the intent that some of these APIs can even be sold as standalone products to consumers. GCP takes the opposite approach: cloud functions are services intended for developers to develop, which covers the vast majority of use cases in my opinion.

Cloud Function Deployment Workflow

To create our first function to serve as an endpoint, we'll utilize the following:

  • Cloud Function running Python 3.7
  • Google's Source Repository: a Github clone with direct access to GCP services
  • Nothing else, actually, other than the gcloud command line tool if you prefer

You should immediately notice the glaring lack of any mentions of API endpoints, methods, stages, or anything related to handling web requests. It should not be understated that Cloud Functions are preconfigured with an endpoint, and all nonsense regarding whether endpoints accept GET or POST or AUTH or OPTIONs is missing entirely. These things are handled in the function itself, and because Google Cloud functions running Python are preconfigured with Flask, all of that stuff is really trivially easy. That's right, we've got Flask, Python, and GCP all in a single post. Typing these words feels like eating cake while Dwyane The Rock Johnson reads me bedtime stories and caresses me as I fall asleep. It's great.

Create your Function

Our function will intend to serve as a Python HTTP endpoint:

Single-page setup. Easy.
  • Trigger specifies what will have access to this function. By selecting HTTP, we will immediately receive a URL.
  • Source code gives us a few options to deploy our code with cloud source repository being by far the easiest solution, especially when working locally.
  • Runtime allows you to select NodeJS by accident.

Before we get to code, let's talk Python libraries.

Including Dependencies in your Function

Our function comes prepared with two files: main.py and our friend requirements.txt. These files do exactly what you'd expect, as per every project ever:

Unfortunately, ease-of-use ensures that GCP certifications will be in low demand.

Our function immediately installs all dependencies in requirements.txt for use upon deployment. Once deployed, we can import these libraries as expected. So, let's deploy something.

Google Source Repositories

Making a commit to a source repo will immediately trigger a build, similar to Heroku, any CI tool, or basically whatever obscenely obfuscated stack you're already using. First create a repo, then start a local project and follow my lead:

$ gcloud source repos create real-repo
$ cd myproject/
$ git init
--------------------------------------------------------
(take a moment to write or save some actual code here)
--------------------------------------------------------
$ git add --all
$ git remote add google https://source.developers.google.com/p/hackers/r/real-repo
$ git commit -m 'cheesey init message'
$ git push --all google

Now make that puppy go live with gcloud functions deploy totally-dope-function, where totally-dope-function is name of your function, as it should be.

Now let's get to the coding part.

The Coding Part ft. Flask

Here's perhaps the most basic endpoint you might ever create:

import requests

def endpoint(request):
    """Does the things."""
    if request.method == 'POST':
    # Allows POST requests from any origin with the Content-Type
    # header and caches preflight response for an 3600s
    headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'POST',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Max-Age': '3600'
    }
    request_json = request.get_json()
    if request_json:
        plaintext = request_json['plain']
        html = request_json['html']
        return html
    else:
        return 'You didn't pass a JSON body you idiot.'

If you're familiar with Flask (you are, because you're on this blog) you already know what all of this does. Look at that simple copy-paste of headers, as opposed to working them into a horrible web interface. Gasp in disbelief as you realize that typing if request.method == 'POST': would be a 10-minute task in a visual API building tool. We've made it fam.

Ease of Logging

Because we have a real endpoint to work with, we don't need to waste any time simulating stupid fucking tests where we send fake JSON to our function. We can use postman or anything to immediately interact with our endpoint, and the logs are a click away:

Easy. Breezy. Beautiful.

There's no point in me droning on at this point because you've surely already ventured into the Google Cloud console in blissful disbelief as a good obedient drone would. If adopting Google Cloud is the last shred of hope we have to resist Google's all-knowing algorithms which have already replaced the illusion of free will, I'd gladly take that dystopia over setting up monolithic API Gateways any day.

Author image
New York City Website
Product manager turned engineer with ongoing identity crisis. Breaks everything before learning best practices. Completely normal and emotionally stable.

Product manager turned engineer with ongoing identity crisis. Breaks everything before learning best practices. Completely normal and emotionally stable.