Go Rest API

This post describes building a stateless Rest API using Go, go-swagger, and Postgres SQL including Docker build process using Alpine Linux.  The demonstration application is hosted on GitHub.

API Specification

swagger is a specification for the definition of a RESTful API around which there is an ecosystem of tools and packages.  go-swagger is a toolkit that will generate a server skeleton and a fully functional client package in Go from a valid swagger specification.

Here is the swagger specification for the demo. app.:

{
  "swagger": "2.0",
  "info": {
    "title": "go-rest-api",
    "version": "1.0.0"
  },
  "produces": [
    "application/json"
  ],
  "consumes": [
    "application/json"
  ],
  "schemes": [
    "http"
  ],
  "definitions": {
    "errorMessage": {
      "type": "object",
      "required": [
        "message"
      ],
      "properties": {
        "message": {
          "type": "string"
        }
      }
    },
    "client": {
      "properties": {
        "id": {
          "format": "int64",
          "type": "integer"
        },
        "name": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "name"
      ],
      "type": "object"
    }
  },
  "paths": {
    "/healthcheck": {
      "get": {
        "responses": {
          "200": {
            "description": "confirm that the service is healthy"
          },
          "default": {
            "description": "generic error response",
            "schema": {
              "$ref": "#/definitions/errorMessage"
            }
          }
        },
        "tags": [
          "healthcheck"
        ]
      }
    },
    "/clients": {
      "get": {
        "responses": {
          "200": {
            "description": "Get all clients",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/client"
              }
            }
          },
          "401": {
            "description": "unauthorised"
          },
          "default": {
            "description": "generic error response",
            "schema": {
              "$ref": "#/definitions/errorMessage"
            }
          }
        },
        "tags": [
          "clients"
        ]
      }
    }
  }
}

A swagger specification can quickly become unwieldy as a single file.  Taking advantage of JSON references the specification can be split into multiple files that are then re-constituted into a single file at build time, in this case using the Node tool json-refs.

As well making sections of the spec. easier to read splitting the paths and definitions into separate files also reduces the potential for merge noise when you have multiple developers working on the same code base.  The split swagger spec is re-constituted into a single file using the code generation script (see line 4).  In order for this to work Node and json-refs must be installed.

go-swagger is currently under very active development.  This demonstration is locked in at version 0.5.0-145-g163c0cd.  Use this script to install this version into your go workspace (passing you gopath as the only arg./install_go-swagger_tools.sh $GOPATH).  go-open-api packages of a version compatible with go-swagger tool are referenced via the Godeps.json file and committed to the vendor folder.

Configuration

Configuration is managed using Vipermask.  There is a config.toml in the repository.  This is optionally masked by an environment.toml file, see line 56 of the initialiser.  This enables environment specific configuration to be injected into the runtime environment as recommended by 12Factor, e.g. at service bootstrap time via Marathon.

Logging

Logging is managed using Loglight and logging.go.

Log output may be structured (JSON) or plain text.  If JSON it may be pretty printed or single line which is useful for shipping logs to Elastic Search for example.  See Microservice Log Aggregation for further discussion of logging.

Every log event has a distinct title which forms a hard reference between a log line and a code line.  Invaluable when debugging or performing fault diagnosis.

go-swagger log output is redirected via line 45 of the initialiser.

SQL Schema Management

SQL schema is managed using Migrate which applies migrations at service bootstrap time.

SQL Interoperation

Interoperation with PostGres is achieved using sqlx.  All statements are prepared at service bootstrap time (see line 5 of the initialiser) so in the event that any statements are invalid against the current schema start-up will fail and the offending statements reported.

Integration Tests

The code generation script creates server skeleton code and a fully functional client library which is used by the integration tests.

Swagger UI

Swagger UI  is a client side app. that can be used to browse and interoperate with a service using it’s swagger spec.  By default a go-swagger service serves a swagger.json from the root.  In order for the swagger UI application to work the service must have CORS enabled, see line 61 of configure_go_rest.go.

Build

To build and run the integration tests complete the following:

  • Install Docker
  • Install NodeJS (brew install node)
  • Install json-refs (sudo npm install json-refs -g)
  • Clone the repository into $GOPATH/src/github.com/mylesmcdonnell
  • Execute ./install_go-swagger_tools.sh $GOPATH
  • Execute ./regen_from_swagger.sh
  • Execute ./bulld_alpine_image.sh
  • Execute docker-compose up
  • Excute go test -v ./integration_tests

Alternatively you can build and run on the host machine rather than in an Alpine container.

If you want to run the server without having to build it you may pull mylesmcdonnell/go-rest-api:latest from docker hub.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s