Cloud Foundry has a lightning fast CLI written in Go, a very well documented API http://apidocs.cloudfoundry.org/, and the API endpoints return consistently structured data. It is ripe for automation. But can we do it with just some bash scripts like sysadmins of old?

Oh yes indeed.

looping

You too can write bash scripts that do magical automation to Cloud Foundry.

cf curl

Firstly, let me introduce you to cf curl. This is like the standard unix tool curl but you are already authenticated.

Look at the http://apidocs.cloudfoundry.org/ and you can GET, POST, PUT or DELETE every resource in Cloud Foundry.

As a user, want a list of all your applications?

cf curl /v2/apps  

As an admin user, want a list of ALL APPLICATIONS?

cf login admin <password>  
cf curl /v2/apps  

The output will look like:

{
   "total_results": 13,
   "total_pages": 1,
   "prev_url": null,
   "next_url": null,
   "resources": [
      {
         "metadata": {
            "guid": "5efa524f-e833-4e35-b73c-c53982cad4f0",
            "url": "/v2/apps/5efa524f-e833-4e35-b73c-c53982cad4f0",
            "created_at": "2014-10-27T17:09:51Z",
            "updated_at": "2014-12-29T22:15:12Z"
         },
         "entity": {
            "name": "starkandwayne-ghost",
...
}

The result is JSON format. You're thinking, oh that's nasty. "Not very nice for bash scripting."

Processing JSON with jq

jq is a CLI tool for processing JSON - but it also comes as an online exploration tool:

jqplay

jq is a little pre-compiled C app that's easy to install on all platforms.

$ echo '{"name": "Dr Nic"}' | jq .
{
  "name": "Dr Nic"
}

$ echo '{"name": "Dr Nic"}' | jq .name
"Dr Nic"

$ echo '{"name": "Dr Nic"}' | jq -r .name
Dr Nic  

Boom! With jq we can now parse out data into simple strings. The flag -r (--raw-output) emits simple strings without JSON quotes.

Using bash-fu we store the results in variables:

$ name=$(echo '{"name": "Dr Nic"}' | jq -r .name)
$ echo "Hello, $name"
Hello, Dr Nic  

cf curl | jq

To get the names of all your applications:

$ cf curl /v2/apps | jq -r ".resources[].entity.name"
starkandwayne-ghost  
trycf  
trycf-dashboard  
...

Put the names in a bash array and loop over them:

names=$(cf curl /v2/apps | jq -r ".resources[].entity.name")  
for name in $names; do  
  echo "App: $name"
done  

Will output:

App: starkandwayne-ghost  
App: trycf  
App: trycf-dashboard  
...

Pagination

Any Cloud Foundry API endpoint that returns a list of resources will pagninate over that list.

You can shrink or grow the number of results per page. For example, two results per page:

$ cf curl "/v2/apps?results-per-page=2"
{
   "total_results": 13,
   "total_pages": 7,
   "prev_url": null,
   "next_url": "/v2/apps?order-direction=asc&page=2&results-per-page=2",
   "resources": [
...

The result includes the URL for the next page of results. We can also get this out with jq:

cf curl "/v2/apps?results-per-page=2" | jq -r .next_url  

Finally, we can now loop over every page of results until we run out of pages:

next_url="/v2/apps?results-per-page=2"  
while [[ "${next_url}" != "null" ]]; do  
  names=$(cf curl ${next_url} | jq -r ".resources[].entity.name")
  for name in $names; do
    echo "App: $name"
  done
  next_url=$(cf curl ${next_url} | jq -r -c ".next_url")
done  

In the example above we're forcing the pages to have only 2 items so the example is more interesting.

looping

Examples

Below are some example bash scripts that interact with Cloud Foundry using cf curl and jq: