Getting Started w/ Ruby on GCP
The “Missing Tutorials” series
Writing a short series of ‘getting started’ posts for those of you, like me, who may get to the point of wanting to write code against a Google service, having a language chosen but then, having not written code for a week or two, I’m stalled by “How exactly do I get started?”
Ruby
OK. I’ve used Ruby twice. Both times were because (and I don’t know why) it appears to be the preferred language for monitoring solutions. I think I used it with Vagrant and with collectd… amiright?
Setup
To avoid supporting the myriad ways you will arrive at this point, I’m just going to tell you what I’m running (Linux), ruby 2.3.3p222 (2016–11–21) [x86_64-linux-gnu] and gems (2.5.2).
PROJECT_ID=[[YOUR-PROJECT-ID]]
LANG=ruby
mkdir -p ${HOME}/${PROJECT_ID}/${LANG}
cd ${HOME}/${PROJECT_ID}/${LANG}https://rubygems.org/gems/googleauthX
Google Ruby Packages
API Client Libraries
https://developers.google.com/api-client-library/ruby/
gems
and… this is rather nice but you can also:
gem search ^google*** REMOTE GEMS ***...
google-api-client (0.13.4)
...
googleauth (0.5.3)
...
rubydoc:
http://www.rubydoc.info/github/google/google-api-ruby-client/Google/APIClient
Gemfile:
source 'https://rubygems.org' do
gem 'googleauth', '0.5.3'
gem 'google-api-client', '0.13.4'
end
Cloud Client Libraries
https://cloud.google.com/ruby/
https://cloud.google.com/ruby/apis
http://googlecloudplatform.github.io/google-cloud-ruby/#/
https://github.com/GoogleCloudPlatform/google-cloud-ruby
Google Cloud Storage (GCS)
As is happening across the languages for the Cloud Client Libraries, Google is moving from “all services” package to “each service” packages. When you review the Cloud Client Libraries documentation for Ruby, please ensure you use the service-specific packages and select the correct documentation:
In order to facilitate writing code that operates on GCS Buckets and Objects, the following script will create (hopefully) a uniquely named bucket for you and populate it with 10 differently named but identical content images. Please set $FILE to a value that paths to a small file that you wish to use as a template.
BUCKET=$(whoami)-$(date +%y%m%d%H%M)
FILE=[[/Path/To/Your/File]]gsutil mb -p ${PROJECT_ID} gs://${BUCKET}
Creating gs://${BUCKET}/...for i in $(seq -f "%02g" 1 10)
do
gsutil cp $FILE gs://${BUCKET}/${i}
donegsutil ls gs://${BUCKET}
gs://${BUCKET}/01
gs://${BUCKET}/02
gs://${BUCKET}/03
gs://${BUCKET}/04
gs://${BUCKET}/05
gs://${BUCKET}/06
gs://${BUCKET}/07
gs://${BUCKET}/08
gs://${BUCKET}/09
gs://${BUCKET}/10
Solution #1: Using API Client Libraries
Experience with other languages leads me to expect there to be a Ruby tool to help with package management. I was aware of gems as the packages of Ruby code (and thus RubyGems.orgs) but, unlike other languages, it appears there’s a separate tool (I found) Bundler to help create deployments.
Gemfile:
source 'https://rubygems.org' do
gem 'googleapis', '0.5.3'
gem 'google-api-client', '0.13.4'
end
and then:
bundle install --path vendor/bundleFetching gem metadata from https://rubygems.org/.........
Fetching version metadata from https://rubygems.org/.
...
Fetching googleauth 0.5.3
Installing googleauth 0.5.3
Fetching google-api-client 0.13.4
Installing google-api-client 0.13.4
Bundle complete! 2 Gemfile dependencies, 22 gems now installed.
Bundled gems are installed into ./vendor/bundle.
third.rb:
require 'googleauth'
scopes = ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/devstorage.full_control']
authorization = Google::Auth.get_application_default(scopes)require "google/apis/storage_v1"
gcs = Google::Apis::StorageV1::StorageService.newgcs.authorization = authorization
When the ‘require’ wouldn’t work with “google/apis/storage”, I was left to check the API Client Library sources:
https://github.com/google/google-api-ruby-client/blob/master/generated/google/apis/storage_v1/service.rb
I was receiving an error:
bundle exec ruby first.rbfirst.rb:9:in `require': cannot load such file -- google/apis/storage (LoadError)
from first.rb:9:in `<main>'
Here it’s clear (line #28) that the include must be:
require 'google/apis/storage_v1'
After changing that, I’d guessed the Google::Apis::StorageV1 correctly and received no errors when:
bundle exec ruby third.rb
The sample “Drive” code on the GitHub page was almost sufficient help to get me to a point where the code lists the Buckets and Objects in a project:
PROJECT_ID = [[YOUR-PROJECT-ID]]
BUCKETNAME = [[YOUR-BUCKETNAME]]require 'googleauth'
scopes = [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/devstorage.full_control'
]
authorization = Google::Auth.get_application_default(scopes)require 'google/apis/storage_v1'
gcs = Google::Apis::StorageV1::StorageService.newgcs.authorization = authorizationbuckets = gcs.list_buckets(PROJECT_ID)
buckets.items.each do |bucket|
puts bucket.name
endobjects = gcs.list_objects(BUCKETNAME)
objects.items.each do |object|
puts object.name
end
This appears to work. I’m sufficiently unfamiliar with Ruby that I’m not comfortable tweaking it too much. If anyone has feedback on better practices, I’d appreciate them.
Proceed to “Testing” below to try this out.
Solution #2: Using Cloud Client Libraries
GCS includes Ruby samples for the Cloud Client Libraries. So, beyond the setup, I’m not going to reproduce that content here.
https://cloud.google.com/storage/docs/listing-buckets#storage-list-buckets-ruby
Using RubyGems:
https://rubygems.org/gems/google-cloud-storage
fourth.rb:
PROJECT_ID = 'dazwilkin-170828-medium'
BUCKETNAME = 'dazwilkin-1708291403'require "google/cloud/storage"storage = Google::Cloud::Storage.new project: PROJECT_IDstorage.buckets.each do |bucket|
puts bucket.name
endbucket = storage.bucket BUCKETNAME
files = bucket.files
files.each do |file|
puts file.name
end
Then
bundle install --path vendor/bundleFetching gem metadata from https://rubygems.org/..........
Fetching version metadata from https://rubygems.org/.
Resolving dependencies...
Fetching public_suffix 3.0.0
Installing public_suffix 3.0.0
Using bundler 1.15.4
...
Fetching googleauth 0.5.3
Installing googleauth 0.5.3
Fetching google-api-client 0.13.4
Installing google-api-client 0.13.4
Fetching google-cloud-core 1.0.0
Installing google-cloud-core 1.0.0
Fetching google-cloud-storage 1.4.0
Installing google-cloud-storage 1.4.0
Bundle complete! 1 Gemfile dependency, 26 gems now installed.
Bundled gems are installed into ./vendor/bundle.
To test this, please proceed to the next section “Testing”.
Testing
I recommend using Application Default Credentials to test your code. This enables config changes only for running the code as an authorized user locally, on App Engine, Compute Engine, and Container Engine. You must:
gcloud auth application-default login
You may also|additionally, authenticate with a service account. To do so, you must create a service account with sufficient permissions (the role ‘roles/storage.admin’ will be sufficient to make the buckets.list and objects.list calls. You must then also set the environment variable:
GOOGLE_APPLICATION_CREDENTIALS=/path/to/your/key.json
Then:
bundle exec ruby third.rb
bundle exec ruby fourth.rb${BUCKET}
01
02
03
04
05
06
07
08
09
10
You may delete the bucket (and its objects) when you’re done. Be *very* careful that you specify the correct bucket when you perform this delete. It deletes all the objects and then the bucket:
gsutil rm -r gs://${BUCKET}
Done.