Friday, May 6, 2016

Learning Swagger.io (Part 2)

I recently started studying and experimenting with a few of the current features of Swagger.io.

My next goal was to create a docker container to hold a few Swagger tools.

Since it had been a long time since I last used docker, I refreshed my skills by creating a tiny little Dockerfile which built a container that holds Ubuntu plus one package: iputils-ping.  I then published it to the public Docker Hub registry.

This simple exercise would remind me how to publish a Dockerfile, and allow me to ensure the running docker container's network interface and DNS lookup was working. More importantly, it would also be a starting point for adding the Swagger tools.

Perhaps I should have called this article Docker 101 :-)

Here's what I did...

Create Local Dockerfile and Docker Container

On a linux machine with the Docker Client installed, I created a subdirectory folder named swagger0/ and created this file named Dockerfile.  You are welcome to copy/paste it.

############################################################
# Dockerfile to create a simple sandbox with
# ping installed.
# 
# Build an image
#    docker build --tag swagger0 .
#
# Run an instance
#    docker run -t -i swagger0
#
# Inspect
#    docker images
#    docker ps -a
#
############################################################

# Start with the latest Ubuntu OS
FROM ubuntu

# Apply latest OS updates
RUN apt-get -y update
RUN apt-get -y dist-upgrade
RUN apt-get -y autoremove 

# Install something small 
RUN apt-get -y install iputils-ping  




Next., I cd'd into the directory containing the Dockerfile, and built a docker image from the Dockerfile:

        docker build --tag swagger0 .

I confirmed by showing the list of images:

        docker images

docker images
  REPOSITORY  TAG     IMAGE ID      CREATED        VIRTUAL SIZE
  swagger0    latest  8b00a84ba944  8 minutes ago  161.2 MB
  ubuntu      latest  686477c12982  38 hours ago   120.8 MB


Then I started an instance of the image and SSH'd into it with this command:

        docker run -t -i swagger0

I was able to ping Google, and confirmed this local container and network were alive.

Save Dockerfile

I copied my Dockerfile to a remote/backup location, since I planned to delete the current working directory where it resided.

Publish to Docker Hub

I created a new account, named btfsplk, at https://hub.docker.com/

To prepare my local container for publishing to docker hub, I tagged it with my docker hub account name.

        docker tag 8b00a84ba944 btfsplk/swagger0:latest

The resulting new image appeared in my list:

        docker images

docker images
  REPOSITORY        TAG     IMAGE ID      CREATED         VIRTUAL SIZE
  btfsplk/swagger0  latest  8b00a84ba944  10 minutes ago  161.2 MB
  swagger0          latest  8b00a84ba944  10 minutes ago  161.2 MB
  ubuntu            latest  686477c12982  38 hours ago    120.8 MB


I logged into my new docker hub account

        docker login

For future reference, it told me that it saved my creds in a file:

        /root/.docker/config.json

I uploaded my image to docker hub

        docker push btfsplk/swagger0

To confirm, I deleted all docker artifacts

    docker ps -a
    docker rm  9d8s849t0

    docker images
    docker rmi ab23nskr9 etc etc

And deleted the subdirectory folder on my disk (confirm you have backed-up the Dockerfile from this location!!)

    rm -rf swagger0

Download from Docker Hub

Finally, the acid test:  I downloaded my container from the Docker Hub repository into a clean sandbox directory.

    docker run -i -t btfsplk/swagger0

It found the image, downloaded it, and started it.  I got dumped into an SSH window.  I confirmed ping was installed as expected:

root@4146b58b8956:/# ping www.google.com
PING www.google.com (74.125.138.104) 56(84) bytes of data.
64 bytes from 74.125.138.104: icmp_seq=1 ttl=35 time=48.1 ms
64 bytes from 74.125.138.104: icmp_seq=2 ttl=35 time=48.1 ms


Yay



Monday, May 2, 2016

Learning Swagger.io (Part 1)

I recently studied and experimented with a few of the current features of Swagger.io...

In the past, I heard different people talking about using Swagger.io for vastly different purposes. I was confused. Some folks were annotating their source code and using Swagger to produce documentation for their REST services. Others were using Swagger docs to automatically generate server-side product code. Others said they were generating mobile client-side code from a Swagger doc. What was going on?

It turns out they were all right.

The basic concept of Swagger.io remains the same.  It's a simple standardized way to represent a REST interface in a document. However, there are now a significant number of tools packages available to produce and consume Swagger.io docs for various purposes.

References 

First, I found a few blog articles from PointSource which caught my interest. http://www.pointsource.com/blog/3-best-practices-for-api-development-with-swagger
and
http://www.pointsource.com/blog/client-side-swagger-support-for-angularjs

I also read a good portion of the Swagger spec:  https://github.com/OAI/OpenAPI-Specification

Name change

Swagger has been donated to the open source community and renamed to Open API Specification.

Getting started

I decided my first goal was to use the online Swagger Editor to define a simple hello world API, and then auto-generate a server-side instance and test it...

Using Swagger Editor

The Swagger Editor is an online tool:  http://editor.swagger.io/#/

I poked around with it a little while.  It's pretty straightforward.  The left panel is an editor where you enter the representation of the API.  The right panel is a live rendering of the Swagger docs created from the left panel.



Create the simplest API you can in the left panel.  Scroll the right panel up and down until you like everything.

Export your definition to a local file for safe-keeping by clicking the upper left tab: File-> Download YAML.

Here is my YAML file.  You are welcome to use it.

# This is an example Swagger API spec in YAML
swagger: '2.0'
info:
  title: Hello World API
  description: This is the exciting Hello World API
  version: "1.2.3"
host: helloworld.com
schemes:
  - https
basePath: /v001
produces:
  - application/json
paths:
  /healthcheck:
    get:
      summary: Returns a known response to indicate service status.
      description: The healthcheck endpoint returns status of the running service.
      tags:
        - User
      responses:
        200:
          description: General information about the running service.
          schema:
            type: object
            properties:
              cpu:
                type: integer
                format: int32
              message:
                type: string
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
definitions:
  Error:
    type: object
    properties:
      code:
        type: integer
        format: int32
        description: Error code.
      message:
        type: string
        description: Human-readable error message.


Auto-generating a server-side instance

My next step was to download a node.js server-side instance which implemented my API.

From the Swagger Editor, click Generate Server-> Node.js   It produces a zip file.  Download it to your machine.

Unzip the file.  Download the dependencies with 'npm install'.  Start the server with 'node index.js'.  Note that the server starts on port 8080 by default.


Confirm it works

The easiest way to confirm the endpoint works is to issue a REST request to it with cURL.  Notice it renders the variable names specified in the YAML, and adds dummy values to them.


Done

This completes the easy part:
  • Manually defining a REST API using Swagger Editor
  • Auto-generating a server-side instance in Node.js
  • Verifying the server-side instance delivers the endpoint
I hope I get time to keep studying...