Skip to content

tedtollefson/data-lifecycle-service-broker

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#Test Env Setup This builds a postgres environment for testing.

  • Create a VPC
  • Create a new ubuntu machine (t1.micro is fine and free)
  • apt-get update
  • Follow the postgres install instructions
  • apt-get install postgressql
  • change the listen_address to * in /etc/postgresql//main/postgresql.conf
  • allow remote connections to pg_hba.conf
  • host all all 0.0.0.0/0 md5
  • connect w/ plsql or pgadmin and add some test data.

#Running Access to AWS via an IAM user. The IAM key needs full EC2 access. The broker relies on AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY being set. Find those keys when you create the user.

#Notes The approach where we take a snap of prod, then make an AMI, then mount it etc may be a little heavy handed. It works for a demo and POC, but in reality we should be leveraging snaps that created by some other schedule.

Also, this broker assumes a pool of free elastic IP's that it can pull from. If describeAddresses comes back with nothing we're in trouble.

#How the service broker works ##Catalog The catalog endpoint offers up two plans. Production works as any normal brokered connection to a database does. The broker injects credentials into your environment and then you change production data. Copy is more devious. This provisions a new VM and copy of the database from a snapshot. The credentials are then inserted, but the data and virtual machine live only as long as the binding lives.

##Provision If plan_id is set to prod, provision doesn't do much of anything.

Upon a provision call with plan_id set to copy, the we will call into AWS to create an AMI from the running instance. What you say? The database is not quiesced? You are correct. #1, As stated in the notes section, in production we should leverage a snap that's created via some other means (like a backup). It is that system's responsibility to ensure a good snapshot. #2, your database is crash consistent, or you should stop whatever you're doing and get one that is. Either way, it's not that big of a deal for this use case as getting the last few seconds of transactions isn't all that import for test data. Depends on the workload & YMMV. Like anything, don't grab code off the internet. Anyway, we create the AMI, and then start an instance from that AMI. We pass the coordinates to the new instance upon bind. There's lots of artifacts that get created along the way by AWS. A snapshot, a volume, an instance. Upon deprovision, we clean them all up.

##Bind Binding dumps the credentials for the copy into VCAP_SERVICES.

#Deployment The broker needs a place to store it's data about running instances (so it can deprovision them). Currently we assume the broker is running in a CloudFoundry instance. Provision a service from the marketplace for the broker to store it's persistent data. I've used postgres, but anything that exposes a DataSource that Spring Cloud supports will work. Here's the docs. Below I use the free plan in PWS, you want something else for production.

cf create-service elephantsql turtle lifecycle-db 

Set the following environment variables. This example uses postgres as the production database and AWS as the copy provider. If you're implementing your own CopyProvider or DataProvider you will set environment variables suitable for your usecase.

export AWS_ACCESS_KEY_ID=<AWS ACCESS KEY>
export AWS_SECRET_ACCESS_KEY=<AWS SECRET KEY>
export SECURITY_USER_NAME=user
export SECURITY_USER_PASSWORD=password
export PROD_DB_PASSWORD=postgres
export PROD_DB_USER=postgres
export PROD_DB_URI postgresql://10.10.10.10:5432/testdb
export SECURITY_USER_NAME=user
export SECURITY_USER_PASSWORD=pass
export SOURCE_INSTANCE_ID=i-xxxxxxx
export SUBNET_ID=subnet-XXXXXX
export BOOT_CHECK_PORT=5432

BOOT_CHECK_PORT is the port that we will try to open a socket connection to to see if the machine is up and booted. If it responds on this port we hand the copy off and say it's good to go. 5432 is the default postgres port, make sure your security groups allow ingress on this port!

After you've exported all that push the app from the same directory as manifest.yml. The manifest assumes you've provisioned a database instance from the marketplace and named it lifecycle-sb-db.

cf push --no-start

Now setup all the environment exported

./set-cf-env.sh

Now start it.

cf start lifecycle-sb

#Console There's a console that gives you an overview of what the service broker is doing running at <sb_url>/. So if you deployed to http://broker.cfapps.io/ you would see the console at that address. The console is primitive, but it does tell you what EC2 instances are running and you can track backwards to find resources if needed. It will show inflight operations too, as those can be a bit hard to track.

#Tests This project separates unit and integration tests by using the maven surefire and failsafe plugins. The integration tests need environment variables described in the deployment section.

From the command line:

	$ mvn test # unit tests
	$ mvn integration-test #integration tests

Eclipse / Intellij targets can be setup by pointing at src/test/java/io/pivotal/cdm/UnitTests.java and src/test/java/io/pivotal/cdm/IntegrationTests.java. Integration tests will need the environment variables setup to function.

The broker API needs a username and password to service API calls. Both the broker and test source these out of the environment, so you can use whatever you want for both values. The AWS variables should come from an IAM user. These tests will start and stop VM's, as well as create and delete snapshots and AMI's in AWS.

I suspect there are limitations around subnet. I've only tested deploying into the same VPC as prod. I've only tested in US-EAST.

##Adding tests Unit tests are simple, just add one. Integration tests use the jUnit category annotation. It points at the spring boot integration test class. This annotation value is then used to tell the test suites what to run. The maven config uses surefire or failsafe to point at the suites.

For example:

	@RunWith(SpringJUnit4ClassRunner.class)
	@SpringApplicationConfiguration(classes = CdmServiceBrokerApplication.class)
	@WebAppConfiguration
	@IntegrationTest("server.port:0")
	@Category(IntegrationTest.class)
	public class CatalogIntegrationTest {
	}

There's tests suites that search for the presence, or lack of the annotation to decide which kind of test it is. In eclipse I have run configur

About

Cloud Foundry Service Broker CDM POC

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 92.4%
  • Shell 4.8%
  • JavaScript 2.3%
  • Other 0.5%