If you thought AWS was fun…

Carrie Walsh
6 min readJul 25, 2019

--

Let’s put our Rails API app on GCP!

(and if you haven’t already read it, https://medium.com/@carriewalsh/yart-yet-another-rails-tutorial-7f7e2fb508e0 is Episode VI and you’re about to read The Empire Strikes Back aka the darker second act that makes you question your fate and the fate of the universe…)

Fun fact about free tier Elastic Beanstalk: if you don’t pay for the domain name, you can’t get an SSL certificate and your site will use http.

Not fun fact: say, oh I don’t know, you have a Heroku frontend that is trying to make fetch calls to your http EB app. It will fail big time (because Heroku uses https).

Solution: Google Cloud Platform (woop!)

There are some parallels and some differences, but ultimately AWS and GCP are equally good at making you want to throw things.

Before we begin!

  • App EngineElastic Beanstalk
  • Cloud SQLRDS
  • This episode does not include automatic deployment like CodePipeline did
  • You’ve got a Rails API made, right? Open that up locally.
  • You’ve got an Google Cloud Platform account? It’s activated? Have you authorized GCP on your GitHub? (https://cloud.google.com/source-repositories/docs/mirroring-a-github-repository will help you figure out how to do that)
  • Get a pen and paper ready to write down names etc so you don’t accidentally put the wrong database name in your database.yml (not that I would know anything about that…) Also, it’s probably best to write them down as key-value pairs like database name: cute_puppies_development so you know what you’re looking at.

All right, let’s get going!

Woo, mining that Google Cloud!

Your first step is to create a new project in GCP. On the top left is a dropdown (that may or may not already have a project name in it). Click that and then click New Project.

Give your project a cute name (but don’t use underscores) and then WRITE THAT DOWN. You probably don’t have an organization, so click Create. It might take a minute to finish up and you’ll see it on the top right in Notifications.

Are you ready for something cool?

See the little >_ icon up at the top right? Click it!

Look, a command line!! That’s your Cloud Shell. You probably had to click “Start Cloud Shell” but now you can use this just like your terminal. Let’s try a few things!

gcloud auth list — This should (hopefully) show your email as the owner

gcloud config list project — This should show the project you made. Yay!

The next command makes sure your Cloud SQL can connect to your project by enabling the Admin API:

gcloud services enable sqladmin.googleapis.com

Now click the “hamburger” menu dropdown on the top left, scroll down to Storage, and find SQL. This is the first difference from AWS. Here you’ll create a Cloud SQL instance and within it live the databases.

Create Instance > PostgreSQL

Now what should you name it? That’s right, the same cute name you wrote down earlier. Give it a password and WRITE THAT DOWN. Choose a region (west coast is the best coast) and Create.

When that’s all ready, you can see your instance and all its details in the SQL dashboard. In a pane, you can see Connect to this instance and there are the Public IP address and the Instance connection name. These are good to write down too (hint hint..).

Still in our Cloud SQL Dashboard

Click Users and see that postgres is already a user. WRITE THAT DOWN. Then click the 3 dots and set the password. WRITE THAT DOWN.

Click Databases and again see that postgres is already a db name. We’re going to create a new one though.

Create Database (you know what you should call it) and, this is the last time I’m going to tell you (you’re a grown up now), WRITE THAT DOWN.

Preparing your local Rails app

Before you connect your actual project, we need to add a few things:

  1. In your Gemfile, add: gem “appengine” and gem “stackdriver”
  • appengine allows you to run rake db:migrate
  • stackdriver makes it a lot easier to read and find errors (which we hopefully won’t have any of)

2. Create an app.yaml file in your root directory. This is what GCP uses to build your app. In that file, put:

entrypoint: bundle exec rackup --port $PORT
env: flex
runtime: ruby
env_variables:
SECRET_KEY_BASE: as234df;abwetiblahblahlongsecret6apowetuhad234
beta_settings:
cloud_sql_instances: <cloud_sql_connectionName>
  • to get your SECRET_KEY_BASE go in your terminal, type rails secret
  • to get your <cloud_sql_connectionName> you can look at the paper where you were supposed to write that down. Otherwise you can a) check in the Cloud SQL dashboard or b) in your Cloud Shell type gcloud sql instances describe <project_name>

3. In your config/database.yml scroll down to development and for database: put the name of the database you created. Now, I’m not going to say this is best practice, but to make things easy for this situation, you’re going to use the same database for production. So, add the following:

production:
<<: *default
pool: 5
timeout: 5000
username: postgres
password: <your_password>
database: <your_database_name>
host: /cloudsql/<that_same_cloud_sql_connectionName>

Time to commit-push-merge to your remote Github repo.

Connecting our App!

This should be very familiar. In your Cloud Shell, you can pwd to find yourself in your project directory. Time to git clone https://github.com/totally_real_username/cute_puppies.git

Then cd into your app directory and bundle

Then bundle exec bin/rails assets:precompile for good measure.

Hope you’re hungry because the next command takes about 10 minutes to run, so you can go make a sandwich:

gcloud app deploy

BUT BEFORE YOU GO!! Both times I did this, it errored out pretty quickly and said INVALID_ARGUMENT unable to resolve source However, when I just ran it again, there were no problems…

You’re Back!

Before we can migrate our database, we need to give appengine authority to do so. In your Cloud Shell run:

gcloud projects list

From that you’ll need the PROJECT_ID and the PROJECT_NUMBER Confusingly enough, the id is not actually a number, but the name of your project. Then run:

gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member=serviceAccount:<PROJECT_NUMBER>@cloudbuild
.gserviceaccount.com \
--role=roles/editor

(The backslashes allow you to run multiple lines in your shell. If it seems a little cranky about that, remove the \'s and try in one line. Also notice the serviceAccount looks like an email address.)

Now for the moment of truth:

bundle exec rake appengine:exec -- bundler exec rake db:migrate

This can take a minute. If you run into a permission error, you might not have done the last step correctly. If it can’t find the database, you may have reached the learning moment of accidentally writing the wrong name in your database.yml. If so, fix the name, commit-push-merge-pull and re-gcloud app deploy

Once migrated, you can then run:

bundle exec rake appengine:exec -- bundler exec rake db:seed

Say you want to check your database?

In your Cloud Shell, run:

gcloud sql connect <database_name> --user=postgres

(wait a little bit…) Then type in your password. There you can run \l to see all your databases \dt to see your tables in that database. Maybe you notice that the tables aren’t there? OH NO! Don’t worry, it’s because it’s in the default database named postgres but you named yours something else. To reach it, run:

\c <your_database_name> postgres <IP_address_of_cloud_sql> 5432

In this command postgres is actually your username and the IP address is the one from your Cloud SQL instance. 5432 is the default port of PostgreSQL.

To get your url, run: gcloud app browse

To check the logs, run: gcloud app logs tail -s default

If you update your app on GitHub, you’ll have to pull down on GCP and re-deploy.

https://console.cloud.google.com/cloud-build — look at your build history!

https://console.cloud.google.com/errors — look at your errors!

YOU DID IT!!

This was a lot. And if you’re like me, it took three tries and 14 hours. If you’re not like me, maybe you got it the first time. Great job! Again, I am by no means an expert. I just wanted to share my learning (and also document it for future Carrie. She will be happy I did.)

Major Tom is proud of you, too.

--

--