Sinatra Starter for Predix: Ruby App with PostgreSQL and Redis
The technical requirements for the Internet of Things (IoT) server applications can substantially differ from the ones applied to the Internet of Humans. First of all, the need for any visual interfaces is completely eliminated.
These step-by-step instructions are intended to guide you through the process of starting a basic Ruby/Sinatra application server on Predix, GE’s IoT platform for the Industrial Internet. From the post, you can learn how to deploy the application to Predix, as well as configure the PostgreSQL database and Redis.
Preparing Sinatra
Sinatra is a simple Ruby framework that has the flexibility to focus on the main task of exchanging information between the server and clients.
Since we are going to concentrate on Predix deployment rather than on preparing a Sinatra application, we’ll use Hazel to streamline the process.
gem install hazel
hazel predix_sinatra_starter -d postgres --redis --rvm --git
Executing these commands generates a proper Sinatra application skeleton prepared to run PostgreSQL through Sequel and with Redis bindings.
You might need to temporarily comment out the Sequel.connect
attempts in config/initializers/database.rb
until you configure the connection. The command below will start the application for you locally to check that it works.
rackup config.ru
To follow along, you can use our sample application.
Deploying the application to Predix
To get started, follow the installation instructions for the Cloud Foundry CLI binaries.
curl -L "https://cli.run.pivotal.io/stable?release=linux64-binary&source=github" | tar -zx
./cf --version
./cf --help
Run the cf login -a https://api.system.aws-usw02-pr.ice.predix.io
command to enter your authentication data.
Cloud Foundry needs the manifest.yml
file for your application, which we’re going to create now in the application root.
applications:
- name: sinatra-app
buildpack: https://github.com/cloudfoundry/ruby-buildpack
memory: 64M
stack: cflinuxfs2
As we work with the Ruby Cloud Foundry buildpack, there are a couple of things we need to do:
- Declare a Ruby version in your
Gemfile
by adding the following line. - Add a
Procfile
starting your application to the root. Ensure it is a valid YAML hash.web: rackup config.ru -p $PORT
Reading from the global
$PORT
variable is crucial here, because Cloud Foundry–based Predix assigns you the port to run on and expects you to use it. - Be sure to add the
.cfignore
file to the root of the application. It should list all files and folders in your project directory tree you don’t want to be uploaded to production.
ruby '2.1.8'
Calling the cf push
command will upload, bundle, and run our simple Sinatra application.
Configuring the PostgreSQL database
Create a local Postgres DB for development.
createdb predix_sinatra_starter_development
Update your Rakefile
with the db:environment
task.
namespace :db do
task :environment do
require 'sequel'
ENV['RACK_ENV'] ||= 'development'
end
end
If you used Hazel to generate your application, rename its default database configuration file config/db.yml
into a standard config/database.yml
file. This is the file the Ruby buildpack will replace with an auto-generated one in production. Make sure the file contains your local database’s address.
development: "postgres://username@localhost/predix_sinatra_starter_development"
Note that the simplest database setup might result in Postgres refusing the connection due to no password being supplied. My usual local development databases run in a not-so-safe mode of allowing any local connections, but you can tweak this step of database setup to use password protection.
Let’s create a migration that will demonstrate we have a proper connection between the application and the database.
db/migrate/001_create_items_table.rb:
Add an indicator that we have data access from Sinatra to views/welcome.erb
:
<%= DB[:items].map(:name) %>
Create a Postgres service as described in Predix Documentation and associate it with your application.
cf create-service postgres shared-nr sinatra-postgres-test
cf bind-service sinatra-app sinatra-postgres-test
cf restage sinatra-app
As we’ve already mentioned, the Ruby buildpack writes a new database.yml
file. However, the file is ERB-enhanced, so it will fail our current application’s database initialization. To avoid that, Sinatra can take a note from Rails, which runs this file through ERB when loading it, to allow various dynamic options.
In the config/initializers/database.rb
file, replace settings = YAML::load_file("config/database.yml")
with the input provided below.
require ‘erb’
settings = YAML.load(ERB.new(File.read('config/database.yml')).result)
Finally, update Procfile
for it to try running the migrations each time we deploy.
To limit the number of times the migration gets triggered, you can add a classic Cloud Foundry Rake task, limiting the Rake execution to only the first instance (when in the batch).
Rakefile
:
namespace :cf do
desc 'Only run on the first application instance'
task :on_first_instance do
instance_index = JSON.parse(ENV["VCAP_APPLICATION"])["instance_index"] rescue nil
exit(0) unless instance_index == 0
end
end
Procfile:
web: bundle exec rake cf:on_first_instance db:migrate && rackup config.ru -p $PORT
Push the new application version:
cf push
Configuring Redis
Setting up Redis requires following pretty much the same steps as configuring PostgreSQL.
cf create-service redis-1 shared-vm sinatra-redis-test
cf bind-service sinatra-app sinatra-redis-test
Modify the Redis initializer to read the configuration from an environment variable.
config/initializers/redis.rb:
if ENV['VCAP_SERVICES']
require 'json'
credentials = JSON.parse(ENV['VCAP_SERVICES'])["redis-1"].first["credentials"]
REDIS = Redis.new(credentials)
end
You can also see this and other production variables by running the following command.
cf env sinatra-app
Deploy the new version.
cf push
Further reading
- Get Started with Predix: Deploying a Rails App and Binding Services
- Using Predix Mobile Services for a Cross-platform App
- Deploying an ASP.NET Application to GE Predix