Command line REST API interface? Yes, please.

Are you a command line-centric developer on a project that has a REST API interface?  Personally, I’ve been getting involved in the Docker community, and looking for an easy way to debug/use the REST API interface without a lot of interaction with other programs or clients.  I know I could use the REST client add-on I already have in my Chrome browser, and a quick search clearly shows there are plenty of other REST clients out there.  However, given I’m sitting at the bash command line inside a VM most of the day, I’d prefer not to break up my workflow with other applications.

Enter resty, a simple bash wrapper around the always-useful cURL binary, which you probably already have installed, or can easily add to your system.  Resty expects to be sourced into your local bash shell, which you can easily automate by putting in a shell startup file, and then provides GET, POST, DELETE and the rest of the HTTP 1.1 methods via shell functions.

That part isn’t necessarily all that amazing; other REST client implementations put scripts in /usr/bin for a similar experience.  However, I like resty’s simple configurability, and to best show it, I’ll share my docker setup here.

Given you’ve followed the link above, downloaded the script and put resty somewhere reasonable, you can manually source it into your environment with:

bash$ . path/to/resty

Secondly, you can give resty a base URL to automatically prepend to your API calls:

bash$ resty http://127.0.0.1:2371

Note: Please don’t append that URL with a trailing slash unless you want a few hours of strange and confusing debugging to figure out that Gorilla Mux, the web server backend used by Docker, sends an HTTP 301 response if there are any extra slashes, and POST retries via curl don’t send the POST body data again after following the redirect.  You can thank me for doing the debug on this head-scratching issue so you don’t have to!

This base URL won’t do you any good unless your Docker daemon is listening on port 2371.  By default Docker only listens on a UNIX domain socket, so you will need to add a “-H 127.0.0.1:2371” to your docker daemon command line.  For a more permanent change, add it to DOCKER_OPTS in /etc/default/docker.  In most cases, you probably want to also continue listening on the domain socket to keep the command line docker client happy, so a complete setting should include both: “-H 127.0.0.1:2371 -H /var/run/docker.sock

A simple test to validate that your setup is correct so far:

bash$ GET /_ping
OK

You’ve validated that you are talking to a Docker daemon over HTTP and received the OK response from Docker’s REST API server.  One more customization to help with POST operations to the Docker API–resty will read a config file for a specific host URL pattern and add the configuration parameters found there automatically for the specific HTTP methods on matching URLs. To add customizations for the Docker host URL pattern, we’ll create a file in $HOME/.resty/ named “127.0.0.1:2371“. The contents of that file in my current setup make sure that we send the right JSON content type header:

POST -H "Content-Type: application/json"

Another simple beauty of resty is that any command line parameters not specific to resty will be passed along to curl, allowing the end user to use any more advanced features of curl from the resty shell wrappers.

Now that our basic setup is complete, we can integrate the use of resty into shell-like workflows.  So, I want to try container creation via API, but rather than create the input JSON from scratch I’d like to start with something already existing:

bash$ docker inspect a390fd | POST /containers/create -V

Now I have the JSON output from the docker inspect command in my $EDITOR of choice and can edit to my liking, and then upon editor exit, that JSON will be POSTed to “/containers/create” at my default host URL with the additional flags I have in the matching host config in $HOME/.resty.  Nice!

Other examples: you can pretty print JSON output from the Docker API using other commonly available JSON tools, such as json_pp:

bash$ GET /images/json | json_pp

Do you already have a program that generates JSON, or static files with boilerplate JSON for certain API calls?

bash$ POST /containers/create < my_container.json
{"Id":"79b574adb1d03a6afd855012b90fcabf9102b16b6721c2a4c1b1531d6453beea","Warnings":null}
bash$ gen_start_json.sh | POST /containers/${CONTAINER_ID}/start

It should be obvious that from this basic beginning the sky’s the limit on what you might be able to script together to combine REST API calls and shell script/command line workflows with Docker or any other REST API you are working on.  Enjoy!

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *