Thursday, December 11, 2014

Talking with DigitalOcean from shell or JSON + bash = rcli

RESTful APIs with JSON are all over the software world.  SaaS, PaaS and other aS'es frequently expose HTTP endpoints that eat and breed JSON. They're fairly easy to work with by using almost any language, except when it comes to do something really simple from a shell script.
Having extremely positive experience with JavaScript library Ramda that makes JSON processing very verbose, I'm now discovering new uses of it's command-line sister - Rcli: Ramda for Command line.

DigitalOcean example
Let's pretend we have a droplet in DigitalOcean and want to run a script on it.
We're going to figure out droplet IP using API and run some script there via ssh. Sounds ideal for bash script.

IP=`curl_get_droplet | \
  R path droplets | \
  R find where '{"name": "example.com"}' | \
  R path networks.v4.0.ip_address`

ssh root@$IP 'bash -s' < script.sh

For simplicity, I replaced exact curl command with curl_get_droplet function. 
For full example, see gist.

The IP address is extracted from DO response in 3 steps:
1. get droplets list from response
2. find the droplet with name "example.com"
3. for that droplet, extract first IP address out of all IPv4 addresses list in network section

{
    "droplets": [
        {
            "backup_ids": [],
            "created_at": "2014-12-11T20:25:40Z",
            "disk": 20,
            "features": [
                "virtio"
            ],
            "id": 3448941,
            "image": {
                "created_at": "2014-10-17T20:24:33Z",
                "distribution": "Ubuntu",
                "id": 6918990,
                "min_disk_size": 20,
                "name": "14.04 x64",
                "public": true,
                "regions": [
                    "nyc1",
                    "ams1",
                    "sfo1",
                    "nyc2",
                    "ams2",
                    "sgp1",
                    "lon1",
                    "nyc3",
                    "ams3",
                    "nyc3"
                ],
                "slug": "ubuntu-14-04-x64"
            },
            "kernel": {
                "id": 2233,
                "name": "Ubuntu 14.04 x64 vmlinuz-3.13.0-37-generic",
                "version": "3.13.0-37-generic"
            },
            "locked": true,
            "memory": 512,
            "name": "example.com",
            "networks": {
                "v4": [
                    {
                        "gateway": "104.236.64.1",
                        "ip_address": "104.236.126.246",
                        "netmask": "255.255.192.0",
                        "type": "public"
                    }
                ],
                "v6": []
            },
            "region": {
                "available": null,
                "features": [
                    "virtio",
                    "private_networking",
                    "backups",
                    "ipv6",
                    "metadata"
                ],
                "name": "New York 3",
                "sizes": [],
                "slug": "nyc3"
            },
            "size_slug": "512mb",
            "snapshot_ids": [],
            "status": "new",
            "vcpus": 1
        }
    ],
    "links": {},
    "meta": {
        "total": 1
    }

}