arbourd / audition

A demonstration of Golang, Hyperapp and Terraform

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Audition

Travis

A demonstration with Golang, Hyperapp and Terraform

Development

Getting Started

Build locally

Both Go (1.8 recommended) and Node.js (8.2 recommended) with yarn must be installed

First, install Node.js dependencies with yarn

$ cd client && yarn

Build the client bundle with webpack

$ yarn dist

Building and run the binary

$ go build -o app .
$ ./app
> Audition is running...

Or just run the app (make sure to exclude *_test.go)

$ go run $(ls *.go | grep -v _test.go)
> Audition is running...

Build with Docker

With docker-compose

$ docker-compose up --build

With docker build/run

$ docker build . -t arbourd/audition
$ docker run --name audition --restart unless-stopped -p 80:8080 -v $(pwd)/db:/db arbourd/audition

Accessing API and Client

Once running either locally or with Docker, the API at localhost:8080/api and the client is available at localhost:8080.

Deploy

Deploy to Digital Ocean with Terraform on CoreOS

You will need to:

  • Install Terraform
  • Get Digital Ocean access token
  • Add (or already have) a SSH key to your Digital Ocean security settings
    • Get the SSH key ID(s) from Digital Ocean API or with doctl: doctl compute ssh-key-list
    • The path of a private key from a corresponding ID above

Variables

Variable Description Type
TF_VAR_do_token Digital Ocean access token string
TF_VAR_ssh_key_ids ID(s) of SSH keys on Digital Ocean list
TF_VAR_private_key Path of private key (defaults to ~/.ssh/id_rsa) string

You can make additional changes to the Terraform configuration by simply editing deploy/main.tf

Provision Instance

From inside the deploy folder, initialize Terraform

$ cd deploy && terraform init

Create a compute instance and deploy app

$ TF_VAR_do_token="accesstoken" TF_VAR_ssh_key_ids="[1234, 4567]" TF_VAR_private_key="~/.ssh/deploy"\
  terraform apply

Destroy compute instance

$ TF_VAR_do_token="accesstoken" TF_VAR_ssh_key_ids="[1234, 4567]" TF_VAR_private_key="~/.ssh/deploy" \
  terraform destroy

These variables can also be exported

$ export TF_VAR_do_token="accesstoken"
$ export TF_VAR_ssh_key_ids="[1234, 4567]"
$ export TF_VAR_private_key="~/.ssh/deploy"
$ terraform apply

SSH Access

To access the box after the fact, simply SSH into using the public IP and the core user

$ ssh core@audition.ip

Starting service

$ sudo systemctl start audition.service

Restarting service

$ sudo systemctl restart audition.service

Starting the container manually without systemd service

$ docker run -d --name audition --restart unless-stopped -p 80:8080 -v $(pwd)/db:/db arbourd/audition

Implementation Architecture

                               ┌────────────────────────────────────────────────────────────────────┐
                               │                                                                    │
                      Serves   │                       Server          ┌────────────────────────┐   │
         ┌────────────GET /────┼─────────────────┐                     │                        │   │
         │                     │                 │                     │   api.go               │   │
         ▼                     │                 │                     │                        │   │
┌─────────────────┐            │                 │                     │   APIService           │   │
│                 │            │                 │                     │   <struct>             │   │
│     Client      │            │                 │                     │   - db Database        │   │
│                 │            │                 │                     │                        │   │
│   index.html    │            │                 │                ┌───▶│   ┌─────────────────┐  │   │
│   bundle.js     │            │     ┌───────────────────────┐    │    │   │     Message     │  │   │
│                 │            │     │                       │    │    │   │ - list all      │  │   │
│        ▲        │            │     │  main.go              │    │    │   │ - get one       │  │   │
│        │        │────────┐   │     │                       │    │    │   │ - create one    │  │   │
│     Webpack     │        │   │     │  - Inits DB           │    │    │   │ - destroy one   │  │   │
│        │        │        │   │     │  - Registers API      │Register │   └─────────────────┘  │   │
│        │        │        │   │     │    handlers           │Handlers └────────────────────────┘   │
│                 │  Calls │   │     │  - Serves requests    │    │                 ▲               │
│   index.html    │   /api └───┼────▶│    w/ mux             │────┘                 │               │
│   index.js      │            │     │                       │                      │               │
│                 │            │     │                       │                      │               │
└─────────────────┘            │     │                       │         ┌────────────────────────┐   │
                               │     │                       │         │                        │   │
                               │     │                       │         │   db.go                │   │
                               │     │                       │         │                        │   │
                               │     └───────────────────────┘         │   Database             │   │
                               │                 │                     │   <interface>          │   │
                               │                 │                     │   - Accesses bolt.DB   │   │
                               │                 │                     │   - CRUD opts for msg  │   │
                               │        .─────.  └─Init DB────────────▶│   ┌─────────────────┐  │◀─┐│
                               │      ,'       `.                      │   │     Message     │  │  ││
                               │     ;  Bolt DB  :                     │   │ - id            │  │  ││
                               │     :messages.db;                     │   │ - message       │  │  ││
                               │      ╲         ╱                      │   │ - isPalindrome  │  │  ││
                               │       `.     ,'                       │   │ - createdAt     │  │  ││
                               │         `───'                         │   └─────────────────┘  │  ││
                               │           ▲                           └────────────────────────┘  ││
                               └───────────┼───────────────────────────────────────────────────────┼┘
                                           └───────────────────JSON serialization──────────────────┘ 

Sequence Diagram

                    ┌─────────────────────┐              ┌─────────────────────┐                ┌─────────────────────┐
                    │                     │              │                     │                │                     │
                    │       Client        │              │       Handler       │                │      Database       │
                    │                     │              │                     │                │                     │
                    └─────────────────────┘              └─────────────────────┘                └─────────────────────┘
                               │                                    │                                      │           
                                                                  ┌───┐                                                
                             ┌─┴─┐         HTTP Request           │   │                                    │           
──────Create a message─────▶ │   │ ─────POST /api/messages────▶   │   │                                                
                             │   │                                │   │                                    │           
                             │   │                                │   │                                                
                             │   │                                │   │                                  ┌─┴─┐         
                             │   │                                │   │   ──────Store in Database────▶   │   │         
                             │   │                                │   │                                  │   │         
                             │   │                                │   │                                  │   │         
                             │   │          HTTP Response         │   │               Message            │   │         
                             │   │  ◀────────201 CREATED────────  │   │    ◀────Serialized as JSON─────  │   │         
                             └─┬─┘                                └─┬─┘                                  └─┬─┘         
                                                                                                                       
                               │                                    │                                      │                

REST API Documentation

Introduction

Authentication

This API has no authentication or authorization

Responses

Successfull responses return JSON either as an object or an array

[
  {
    "name": "example",
    "value": 0
  }
]

Errors

Errors are returned as JSON with an error attribute and a message. Example:

{
  "error": "Not Found",
  "message": "Could not find an object with ID: 0"
}

Messages

Attributes of a message

Name Type Description
id integer A unique ID used to identify the message
message string The value of the message itself
isPalindrome boolean Whether or not the message is a palindrome
createdAt string A time value of when the message object was created

Retrieve all Messages

GET /api/messages

cURL example

$ curl -X GET -H "Content-Type: application/json" "http://audition.arbr.ca/api/messages" 

Response headers

Content-Type: application/json
Status: 200

Response body

[
  {
    "id": 1,
    "message": "hello",
    "isPalindrome": false,
    "createdAt": "2017-07-30T23:42:20Z"
  },
  {
    "id": 2,
    "message": "anna",
    "isPalindrome": true,
    "createdAt": "2017-07-30T23:42:24Z"
  }
]

Retrieve an existing Message

GET /api/messages/id

cURL example

$ curl -X GET -H "Content-Type: application/json" "http://audition.arbr.ca/api/messages/1" 

Response headers

Content-Type: application/json
Status: 200

Response body

{
  "id": 2,
  "message": "anna",
  "isPalindrome": true,
  "createdAt": "2017-07-30T23:42:24Z"
}

Create a Message

POST /api/messages

Request params

{
  "message": "The quick brown fox!"
}

cURL example

$ curl -X POST -H "Content-Type: application/json" -d '{"message":"The quick brown fox!"}' \
  "http://audition.arbr.ca/api/messages" 

Response headers

Content-Type: application/json
Status: 201

Response body

{
  "id": 3,
  "message": "third",
  "isPalindrome": false,
  "createdAt": "2017-07-30T23:46:20Z"
}

Delete a Message

DELETE /api/messages/id

cURL example

$ curl -X DELETE -H "Content-Type: application/json" "http://audition.arbr.ca/api/messages/1" 

Response headers

Content-Type: application/json
Status: 204

About

A demonstration of Golang, Hyperapp and Terraform

License:MIT License


Languages

Language:Go 51.4%Language:JavaScript 29.8%Language:HCL 8.2%Language:CSS 5.9%Language:Dockerfile 3.5%Language:HTML 1.2%