100-day Challenge #068: Running spring-boot-cf-service-broker-mongo on Cloud Foundry

By: | April 15, 2016
Share

Translator’s note: This is the 16th article of the series “Cloud Foundry 100-day Challenge selection”. “#068” in the title means that it is 68th (published on September 29, 2015) in the original Japanese series.

Original Author: Takeshi MORIKAWA (GitHub) (company)


The 68th topic of “Cloud Foundry 100-Day Challenge” is spring-boot-cf-service-broker-mongo. This is an application that works as a Cloud Foundry (“CF”) service broker, in a category similar to postgresql-cf-service-broker from Article #002. By deploying it, the application allows us to easily use MongoDB as a service.

Basic Information

The overall process can be summarized in the below image:

The procedure can be summarized as follows:

  1. Preparing MongoDB (ver. 2.6) instance
  2. Deploying spring-boot-cf-service-broker-mongo
  3. Making application usable as service broker

Preparing MongoDB (ver. 2.6) Instance

Since this is for a experimental purpose, we decided to prepare MongoDB (ver 2.6) with Docker.

The summary of this section is as follows:

  • 1) Installing Docker
  • 2) Installing MongoDB Client
  • 3) Running MongoDB Docker Image

Installing Docker

CF runs on Ubuntu, so we will also run the MongoDB Docker image on Ubuntu. First, we install Docker on Ubuntu.

$ sudo apt-get install -y docker.io

Verification:

$ sudo docker version
Client:
 Version:      1.8.2
 API version:  1.20
 Go version:   go1.4.2
 Git commit:   0a8c2e3
 Built:        Thu Sep 10 19:19:00 UTC 2015
 OS/Arch:      linux/amd64

Server:
 Version:      1.8.2
 API version:  1.20
 Go version:   go1.4.2
 Git commit:   0a8c2e3
 Built:        Thu Sep 10 19:19:00 UTC 2015
 OS/Arch:      linux/amd64

Installing MongoDB Client

NOTE: The purpose of this process is to enable checking MongoDB. It is not essential for running spring-boot-cf-service-broker-mongo, so it can be omitted.

$ sudo apt-get install -y mongodb-clients

Verification:

$ mongo --version
MongoDB shell version: 2.4.9

Running MongoDB Docker Image

Retrieving Docker Image

$ sudo docker pull mongo:2.6

NOTE: The version of MongoDB is specified by the tag 2.6 because spring-boot-cf-service-broker-mongo will not work properly unless the version of MongoDB is 2.6.

Starting Docker Image

While setting the host’s port 27017 to transfer to the container’s port 27017, start the obtained Docker image.

$ sudo docker run -p 27017:27017 -d mongo:2.6

Checking Connectivity

$  mongo --port 27017
MongoDB shell version: 2.4.9
connecting to: 127.0.0.1:27017/test

This completes the preparation of the MongoDB instance.

Deploying spring-boot-cf-service-broker-mongo

Next, we deploy spring-boot-cf-service-broker-mongo on CF.

This is the summary of procedures:

  • 0) Preparing for Deployment
    • 0.1) Installing JDK and Gradle
    • 0.2) Retrieving Source Code
    • 0.3) Modifying Source Code
    • 0.4) Building Application
    • 0.5) Creating Org and Space
    • 0.6) Configuring Application Security Group
  • 1) Deployment
    • 1.1) Pushing Application

Preparing for Deployment

Installing JDK and Gradle

As the name suggests, this is a spring-boot application, so we install JDK and Gradle.

Oracle JDK 8

We retrieve a tarball that is proper for our environment from the page of Oracle JDK 8.

NOTE: At the time of the article, the latest version is jdk-8u60-linux-x64.tar.gz.

$ ls -lha jdk-8u60-linux-x64.tar.gz
-rw-rw-r-- 1 morika-t morika-t 173M Aug  7 08:32 jdk-8u60-linux-x64.tar.gz

Expand the tarball:

$ tar zxfv jdk-8u60-linux-x64.tar.gz

Configure JAVA_HOME and PATH.

$ export JAVA_HOME=~/work/jdk1.8.0_60
$ export PATH=$JAVA_HOME/bin:$PATH

Check the version:

$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
Gradle
$ wget https://services.gradle.org/distributions/gradle-2.5-all.zip
$ unzip gradle-2.5-all.zip

Configure GRADLE_HOME and PATH.

$ export GRADLE_HOME=~/work/gradle-2.5
$ export PATH=$GRADLE_HOME/bin:$PATH

Check the version:

$ gradle -version
------------------------------------------------------------
Gradle 2.5
------------------------------------------------------------

Build time:   2015-07-08 07:38:37 UTC
Build number: none
Revision:     093765bccd3ee722ed5310583e5ed140688a8c2b

Groovy:       2.3.10
Ant:          Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM:          1.8.0_60 (Oracle Corporation 25.60-b23)
OS:           Linux 3.13.0-55-generic amd64

Retrieving Source Code

Clone the source code of the application from GitHub.

$ git clone https://github.com/spgreenberg/spring-boot-cf-service-broker-mongo
$ cd spring-boot-cf-service-broker-mongo

Modifying Source Code

Before building the application, we will modify the source code to adjust the application to Service Broker API version 2.5 which is supported by cf-release v211, the environment used in this post.

NOTE: Version 2.4 of Service Broker API is the version that corresponds to the latest code for spring-boot-cf-service-broker-mongo at the time of this article.

Modification to Not Verify Header for Service Broker API Version

Reference URL: https://github.com/cloudfoundry-community/spring-boot-cf-service-broker/blob/a30748549291e6ab2b0b793be3514b249708f47c/README.md#api-version-verification

$ vi src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
$ git diff src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
diff --git a/src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java b/src/main/java/org/cloudfoundry
index 295b844..9b51e87 100644
--- a/src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
+++ b/src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
@@ -8,6 +8,7 @@ import java.util.Map;
 import org.cloudfoundry.community.servicebroker.model.Catalog;
 import org.cloudfoundry.community.servicebroker.model.Plan;
 import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
+import org.cloudfoundry.community.servicebroker.model.BrokerApiVersion;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;

@@ -15,6 +16,11 @@ import org.springframework.context.annotation.Configuration;
 public class CatalogConfig {

        @Bean
+       public BrokerApiVersion brokerApiVersion() {
+               return new BrokerApiVersion();
+       }
+
+       @Bean
Modification to Add requires: syslog_drain in Service Catalog

Reference URL:
http://cf-dev.70369.x6.nabble.com/cf-dev-Document-for-service-broker-api-version-2-5-tp537p582.html
http://docs.cloudfoundry.org/services/app-log-streaming.html

$ vi src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
$ git diff src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
@@ -30,7 +36,7 @@ public class CatalogConfig {
                                                                        getPlanMetadata())),
                                        Arrays.asList("mongodb", "document"),
                                        getServiceDefinitionMetadata(),
-                                       null,
+                                       Arrays.asList("syslog_drain"),
                                        null)));
        }
Configuring MongoDB Connection
$ vi src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/MongoConfig.java
$ git diff src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/MongoConfig.java
diff --git a/src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/MongoConfig.java b/src/main/java/org/cloudfoundry/c
index 4f403c0..d12c07a 100644
--- a/src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/MongoConfig.java
+++ b/src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/MongoConfig.java
@@ -14,7 +14,7 @@ public class MongoConfig {

        @Bean
        public MongoClient mongoClient() throws UnknownHostException {
-               return new MongoClient();
+               return new MongoClient("192.168.15.91", 27017);
        }

 }

Building Application

$ ./gradlew build -x test

Creating Org and Space

Like postgresql-cf-service-broker from Article #002 , we create a specific org and space for deploying the service broker.
We took and used one created in the previous article; when creating from scratch, the following commands need to be run:

$ cf create-org admin
$ cf create-space svcs

Configuring Application Security Group

The environment for this post is built with bosh-lite, whose default settings do not allow applications to connect to private addresses (10.*.*.*, 192.168.*.*). The MongoDB we built this time exists on 192.168.*.*, so we configure a security group for it.

Creating Security Group

We create an application security group that allows access to the MongoDB instance built previously.

First, we create a file with rules (in JSON format).

$ vi ~/spring-boot-cf-service-broker-mongo.security-groups.json
$ cat ~/spring-boot-cf-service-broker-mongo.security-groups.json
[
    {
        "protocol": "tcp",
        "destination": "192.168.15.91",
        "ports": "27017"
    }
]
Registering Security Group
$ cf create-security-group spring-boot-cf-service-broker-mongo-security-groups ~/spring-boot-cf-service-broker-mongo.security-groups.json

Verification:

$ cf security-group spring-boot-cf-service-broker-mongo-security-groups
Getting info for security group spring-boot-cf-service-broker-mongo-security-groups as admin
OK

Name    spring-boot-cf-service-broker-mongo-security-groups
Rules
        [
                {
                        "destination": "192.168.15.91",
                        "ports": "27017",
                        "protocol": "tcp"
                }
        ]

No spaces assigned
Binding to Default Running Security Group

By configuring these settings, all applications on the same CF will be able to access the MongoDB instance when run.

$ cf bind-running-security-group spring-boot-cf-service-broker-mongo-security-groups

Deployment

Pushing Application

We just cf push, as manifest.yml is already prepared.

$ cf push
App started


OK

App mongo-broker was started using this command `SERVER_PORT=$PORT $PWD/.java-buildpack/open_jdk_jre/bin/java -cp $PWD/.:$PWD/.java-bu
ildpack/spring_auto_reconfiguration/spring_auto_reconfiguration-1.10.0_RELEASE.jar -Djava.io.tmpdir=$TMPDIR -XX:OnOutOfMemoryError=$PW
D/.java-buildpack/open_jdk_jre/bin/killjava.sh -Xmx382293K -Xms382293K -XX:MaxMetaspaceSize=64M -XX:MetaspaceSize=64M -Xss995K org.spr
ingframework.boot.loader.WarLauncher`

Showing health and status for app mongo-broker in org admin / space svcs as admin...
OK

requested state: started
instances: 1/1
usage: 512M x 1 instances
urls: mongo-broker.10.244.0.34.xip.io
last uploaded: Thu Sep 24 09:25:12 UTC 2015
stack: cflinuxfs2
buildpack: java-buildpack=v3.0-https://github.com/cloudfoundry/java-buildpack.git#3bd15e1 java-main open-jdk-jre=1.8.0_60 spring-auto-
reconfiguration=1.10.0_RELEASE

     state     since                    cpu     memory           disk      details
#0   running   2015-09-24 06:25:57 PM   11.9%   329.8M of 512M   0 of 1G

Making Aplication Usable as Service Broker

We let the CF environment recognize the application as a service broker. The summary of procedures in this section are as follows:

  • 1) Checking Credentials for Service Broker Registration
  • 2) Registering as Service Broker
  • 3) Checking Label Information to Enable Access on Marketplace
  • 4) Enabling Access on Marketplace

Checking Credentials for Service Broker Registration

We check the log using the --recent option of cf logs.

$ cf logs mongo-broker --recent

The section after password: in the following log is the password used for Service Broker registeration.
The user name is fixed as user.

2015-09-25T10:32:39.97+0900 [App/0]      OUT 2015-09-25 01:32:39.972  INFO 29 --- [           main] b.a.s.AuthenticationManagerConfiguration :
2015-09-25T10:32:39.97+0900 [App/0]      OUT Using default security password: cbbed27c-b42a-489b-8d1b-ce3cb9c6e779
2015-09-25T10:32:40.24+0900 [App/0]      OUT 2015-09-25 01:32:40.245  INFO 29 --- [           main] s.b.c.e.t.TomcatEmbeddedServletCon
tainer : Tomcat started on port(s): 61139/http
2015-09-25T10:32:40.24+0900 [App/0]      OUT 2015-09-25 01:32:40.248  INFO 29 --- [           main] o.c.c.s.mongodb.config.Application
       : Started Application in 7.613 seconds (JVM running for 8.284)

Registering as Service Broker

$ cf create-service-broker mongodb user cbbed27c-b42a-489b-8d1b-ce3cb9c6e779 http://mongo-broker.10.244.0.34.xip.io

Checking Label Information to Enable Access on Marketplace

The label name for registration is “Mongo DB”. To check the value, we look at the value of the second argument of ServiceDefinition of CatalogConfig.java.

$ vi src/main/java/org/cloudfoundry/community/servicebroker/mongodb/config/CatalogConfig.java
 23         @Bean
 24         public Catalog catalog() {
 25                 return new Catalog( Arrays.asList(
 26                                 new ServiceDefinition(
 27                                         "mongo",
 28                                         "Mongo DB",
 29                                         "A simple mongo implementation",
 30                                         true,
 31                                         false,

Enabling Access on Marketplace

By completing this procedure, we provide the service plan to all users.

$ cf enable-service-access "Mongo DB"

Verification:

$ cf service-access
broker: mongodb
   service    plan                 access   orgs
   Mongo DB   Default Mongo Plan   all
$ cf marketplace
service      plans                     description
Mongo DB     Default Mongo Plan*       A simple mongo implementation

Checking Service Broker Behavior using Sample Application

Creating Service

$ cf create-service 'Mongo DB' 'Default Mongo Plan' mongodb-test

Cloning Sample Application

We clone a simple Sinatra application that uses MongoDB.

https://github.com/nota-ja/app-sinatra-mongodb.git

$ git clone https://github.com/nota-ja/app-sinatra-mongodb.git
$ cd app-sinatra-mongodb

Pushing Sample Application

$ cf push sinatra-mongo --no-start

Binding Service

$ cf bind-service sinatra-mongo mongodb-test

Starting Sample Application

$ cf start sinatra-mongo

Reading from / Writing to MongoDB

Here, let’s store the data “Taro” to the key “1”.

$ curl -X POST http://sinatra-mongo.10.244.0.34.xip.io/service/mongo/1 -d 'Taro'

We get an output that confirms “Taro”.

Taro

Then read the data for key name “1”.

$ curl http://sinatra-mongo.10.244.0.34.xip.io/service/mongo/1

We get back the stored “Taro”.

Taro

Let’s restart the application.

$ cf restart sinatra-mongo

And read the data for key name “1” again.

$ curl http://sinatra-mongo.10.244.0.34.xip.io/service/mongo/1

The data is persistent even after a restart, so we still get back the stored data “Taro”.

Taro

Software Used in This Post