ActiveBlog

User Provided Service Instances: Use Them!
by Troy Topnik

Troy Topnik, April 24, 2014
Horton finds a feature

There's a feature in Cloud Foundry v2 and Stackato 3 that a lot of people seem to miss. User-Provided Service Instances let you store service connection information and credentials using the same JSON-formatted environment variables that system-provided services create when you bind a service to an application.

In short, it's the simplest possible way to connect applications running on Stackato to *existing* data services. Enter the connection strings via the 'stackato' client, then bind the resulting service instance to your app.

A feature's a feature, no matter how small.

A lot of PaaS systems use environment variables to set configuration and attach applications to services. Storing config in the environment is the third factor in the Twelve-Factor App approach.

The database binding system has been in Cloud Foundry from the start, and thankfully, someone at Pivotal noticed some low-hanging fruit when planning and implementing Cloud Foundry v2.

With the service instance binding model already in place, it was relatively trivial to give users the ability to specify arbitrary key-value pairs from the CLI client and enable them to connect their applications. Stackato inherited this in version 3.0 with the move to the v2 code base.

How services are bound to apps

When you push an application to Stackato, you can request a data service for it. Here's an example in stackato.yml format:

  name: cirrus
  mem: 256M
  instances: 2
  services:
      cirrusdb: mysql

Our application, called 'cirrus', requests 256M of application memory for each of two instances (Docker containers). It also requests a MySQL database, which Stackato will create.

Stackato's user-facing name for this service instance is 'cirrusdb' but that's not the *actual* database name in MySQL. Depending on how the system service is implemented, the database name may need to be globally unique, so generally the connection information for a service instance like 'cirrusdb' might look something like this:

  host: 192.168.68.18
  name: dd8b072e1950844aa8af62911132898a5 
  password: pQaVO9oAd6dJR
  port: 3306
  user: uIcTojXrnLWyE

The service *instance* is really just a handle for a JSON object with all of the *real* information the application needs to connect to the database. This information is exposed inside the application instances by way of environment variables such as VCAP_SERVICES:

   $ echo $VCAP_SERVICES | json
  {
    "mysql": [
      {
        "name": "cirrusdb",
        "label": "mysql-5.5",
        "tags": [],
        "plan": "free",
        "credentials": {
          "name": "dd8b072e1950844aa8af62911132898a5",
          "hostname": "192.168.68.18",
          "host": "192.168.68.18",
          "port": 3306,
          "user": "uZ3e0I7b3w578",
          "username": "uZ3e0I7b3w578",
          "password": "p0IOGF5wYA337",
          "uri": "mysql://uZ3e0I7b3w578:p0IOGF5wYA337@192.168.68.18:3306/dd8b072e1950844aa8af62911132898a5",
          "jdbcUrl": "jdbc:mysql://uZ3e0I7b3w578:p0IOGF5wYA337@192.168.68.18:3306/dd8b072e1950844aa8af62911132898a5"
        }
      }
    ]
  }

...and the slightly simpler STACKATO_SERVICES:

  $ echo $STACKATO_SERVICES | json
  {
    "cirrusdb": {
      "name": "dd8b072e1950844aa8af62911132898a5",
      "hostname": "192.168.68.18",
      "host": "192.168.68.18",
      "port": 3306,
      "user": "uZ3e0I7b3w578",
      "username": "uZ3e0I7b3w578",
      "password": "p0IOGF5wYA337",
      "uri": "mysql://uZ3e0I7b3w578:p0IOGF5wYA337@192.168.68.18:3306/dd8b072e1950844aa8af62911132898a5",
      "jdbcUrl": "jdbc:mysql://uZ3e0I7b3w578:p0IOGF5wYA337@192.168.68.18:3306/dd8b072e1950844aa8af62911132898a5"
    }
  }

The application can parse one of these variables (or the even more succinct _URL variables) to connect itself to the database. Simple.

But how do I connect to the production DB?

All of the above works great if you're using Stackato to provision all databases all the time, but a lot of people already have data in existing production databases. Connecting applications hosted on Stackato to these systems used to (back in 2.x days) require manually specifying additional environment variables in the application containers and adding extra tests/parsing in the application code.

It worked, but it wasn't very elegant. It wasn't that much better than hard-coding connection strings, which we've been exhorting people to avoid.

Now there's a better way to store those connection strings.

Say we have a big, high-availability MySQL cluster on our network. Our production data is already there, and I've been given credentials to connect the appropriate database with a certain username and password. The Stackato admin has made sure the DEA nodes in our Stackato cluster can route to the host that is load-balancing the DB cluster.

I take the connection details I've been given and enter them as a user-provided service instance using the stackato client:

  $ stackato create-service user-provided cirrusdb-prod-live
  Which credentials to use for connections [hostname, port, password]: hostname, port, name, user, password
  hostname: bigdb.int.example.com
  port: 3306
  name: cirrusdb-prod
  user: cirrus-web-ro
  password: n63uYdetMH8qAkysoL
  Creating new service ... OK

We now have a "service instance" called "cirrusdb-prod-live" so we can swap our test database:

  $ stackato unbind-service cirrusdb cirrus
  Unbinding cirrusdb from cirrus ...
  ...

...for one with live data in it:

  $ stackato bind-service cirrusdb-prod-live cirrus
  Binding cirrusdb-prod-live to cirrus ...

My application will pick up the connection details from VCAP_SERVICES or STACKATO_SERVICES and start using the live data.

Not just for databases.

Since you control the keys and the values saved in the service instance, you can use it to connect your application to *any* type of service that requires a connection string or credentials (e.g. an SMTP server, a REST interface, a message queue).

As long as your application has the libraries needed to connect to the service, and Stackato can route to the service endpoint (the host), you're good to go.

Share this post:


If you'd like to try Stackato for yourself, you can download the micro cloud for free or request access to the Stackato sandbox for a trial period.

Subscribe to ActiveState Blogs by Email

Share this post:

Category: stackato
About the Author: RSS

Troy Topnik is ActiveState's technical writer. After joining ActiveState in 2001 as a "Customer Relationship Representative" (AKA Tech Support), Troy went on to lead the PureMessage Enterprise Support team before moving on to a technical writing role in 2004. His talent for describing software for new users stems from his difficulty understanding things that developers find obvious. He has a Bachelor of Music from the University of Victoria.