Bind a Service to Your App

Page last updated:

Page last updated:

The service marketplace has a large number of data stores, from Redis and MongoDB, to MariaDB (fork of MySQL) and RabbitMQ. You can run cf marketplace to get an overview. In this step you will add a small MariaDB database to your app.

Create the database:

$ cf create-service mariadb small my-mariadb
Creating service instance my-mariadb in org MyOrg / space MySpace as user@mydomain.com...
OK

Create in progress. Use 'cf services' or 'cf service my-mariadb' to check operation status.

Attention: The plan `small` of service `mariadb` is not free.  The instance `my-mariadb` will incur a cost.  Contact your administrator if you think this is in error.

This creates a small MariaDB database for you which we now have to bind to our application. Binding means that the credentials and URL of the service will be written dynamically into the environment variables of the app as VCAP_SERVICES and can hence be used directly from there.

Let’s bind the new service to our existing application:

$ cf bind-service my-ruby-app my-mariadb
Binding service my-mariadb to app my-ruby-app in org MyOrg / space MySpace as user@mydomain.com...
OK
TIP: Use 'cf restage my-ruby-app' to ensure your env variable changes take effect

After that we restage the application as suggested so that it includes the new credentials in its environment variables:

$ cf restage my-ruby-app
Restaging app my-app in org MyOrg / space MySpace as user@mydomain.com...
-----> Downloaded app package (8.0K)
-------> Buildpack version 1.6.14
-----> Creating runtime environment

...

Now we want to consume our new MariaDB from within our application. Change the Gemfile to add the sequel, mysql and json modules to your dependencies:

source 'https://rubygems.org'

gem 'puma'
gem 'rack-coffee'

group :web do
  gem 'sequel'
  gem 'json'
  gem 'haml'
  gem 'sinatra'
  gem 'sass'
  gem 'mysql'
end

group :development do
  gem 'sinatra-reloader'
end

Now run bundle install again to install these new dependencies:

$ bundle install
Using backports 3.3.5
Using coffee-script-source 1.6.2
Using multi_json 1.7.6
Using tilt 1.4.1

...

Now edit your app.rb file to use these modules to connect to the database specified in your VCAP_SERVICES environment variable. We do this by adding a connection to the database, creating a kittens table and a route for the /kittens endpoint which returns the table of our MariaDB:

# require dependencies
Bundler.require :web
Bundler.require :development if development?

# check if running in the cloud and setting the MariaDB settings accordingly
if ENV['VCAP_SERVICES']
  vcap_services = JSON.parse(ENV['VCAP_SERVICES'])
  DB = Sequel.connect(vcap_services['mariadb'][0]['credentials']['uri'])
else
  DB = Sequel.connect('mysql://localhost:3306/dbname')
end

# create database table for our kittens
DB.create_table? :kittens do
  primary_key :id
  String :name
end

# serve stylesheet
get '/style.css' do
  scss :style
end

# our basic route which renders the index view
get '/' do
  haml :index
end

# here you can retrieve all the kittens in our MariaDB
get '/kittens' do
  content_type :json
  kittens = DB[:kittens].all
  kittens.to_json
end

# endpoint to create a new kitten (e.g. /kittens?name=garfield)
post '/kittens' do
  kitten_name = params[:name]
  DB[:kittens].insert(:name => kitten_name)
  "Kitten #{kitten_name} added"
end

# our not-found route which serves the 404 view
not_found do
  haml :'404'
end

This ensures that when you access your app using the /kittens route, it will return all the kittens stored in your database. Currently there are no kittens so it will return an empty array. Sad…

But you can create new kittens by POST-ing to the /kittens endpoint with the kitten’s name as a URL query parameter. You can do so using curl or any similar tool:

$ curl -X POST "http://localhost:3000/kittens?name=garfield"

and then retrieve your new kitten at the /kittens endpoint.

The line

if ENV['VCAP_SERVICES']

checks if the app is running in the cloud. If not, it falls back to the default local MariaDB url. This allows you to run your app locally as well as in the cloud without having to configure anything differently. So let’s push it to the cloud using

$ cf push my-ruby-app

You can access other services like Redis or MongoDB in a similar matter, simply by binding them to your app and accessing them through the environment variables.

I’ve bound a service to my App
View the source for this page in GitHub