Home

Awesome

Luntic

A lightweight REST in-memory discovery service.

Features:

The service was inspired by Eureka web service and it uses for registration and locating services in your environment.

It uses REST JSON-based API for simple integration.

Contents

Getting Started

Start the Luntic discovery server:

$> luntic

    __                  __   _
   / /   __  __ ____   / /_ (_)_____
  / /   / / / // __ \ / __// // ___/
 / /___/ /_/ // / / // /_ / // /__
/_____/\__,_//_/ /_/ \__//_/ \___/

I was born!

v1.1.0
Copyright (c) by Artem Labazin

REST requests are serviced on: http://0.0.0.0:8080/

If you need to launch Luntic on different port, with specific path prefix, debug access logs or public net address, you are able to set it:

$> luntic --debug --port=9999 --path-prefix=/register localhost

    __                  __   _
   / /   __  __ ____   / /_ (_)_____
  / /   / / / // __ \ / __// // ___/
 / /___/ /_/ // / / // /_ / // /__
/_____/\__,_//_/ /_/ \__//_/ \___/

I was born!

v1.1.0
Copyright (c) by Artem Labazin

REST requests are serviced on: http://localhost:9999/register

2017-07-22T03:20:45+03:00 -- POST   /register/popa
2017-07-22T03:21:12+03:00 -- GET    /register
2017-07-22T03:21:28+03:00 -- DELETE /register/popa/59729a5d8b7df47200000001

We could also start a simple web browser dashboard on separate port:

$> luntic --dashboard:9876

    __                  __   _
   / /   __  __ ____   / /_ (_)_____
  / /   / / / // __ \ / __// // ___/
 / /___/ /_/ // / / // /_ / // /__
/_____/\__,_//_/ /_/ \__//_/ \___/

I was born!

v1.1.0
Copyright (c) by Artem Labazin

REST requests are serviced on: http://0.0.0.0:8080/
Dashboard is available on: http://0.0.0.0:9876/

Open the link http://localhost:9876 in your web browser and you could see something like this:

home page

And see group info:

group info

Also there is a API page:

api page

To see all available switches and keys, type the following:

$> luntic --help

Usage:  luntic [OPTIONS] [LISTENING_ADDRESS]

A lightweight REST in-memory discovery service

Options:
    -p:PORT --port=PORT   sets listening port
                          default: 8080
    --path-prefix=PATH    sets server's endpoints path prefix
                          default: '/'
    --heartbeat=SECONDS   sets heartbeat service cleaner in seconds,
                          if it set to 0 - turn off heartbeat scheduler
                          default: 0s
    --dashboard=PORT      setups a simple web browser-oriented dashboard
                          for services monitoring
                          default: turned off
    -d --debug            turn on debug mode
    -v --version          prints program's version
    -h --help             prints this help menu

After starting Luntic server you could register your first app via REST API. I am using HTTPie for request calls, but you can do it with cURL or Postman.

Registering a new app, which has popa group name:

$> http -v POST :8080/popa
POST /popa HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 0
Host: localhost:8080
User-Agent: HTTPie/0.9.9


HTTP/1.1 201 Created
Content-Length: 124
content-type: application/json
location: /popa/597298af0937867200000001
x-expired-time: 0

{
    "created": "2017-07-22T03:13:35+03:00",
    "group": "popa",
    "id": "597298af0937867200000001",
    "modified": "2017-07-22T03:13:35+03:00"
}

As we can see, we have created a new record in popa application group. The server have generated the instance id 597298af0937867200000001, creation time and last modified time fields.

We are also able to attach our own JSON object to a record in meta field during its creation:

$> http -v POST :8080/popa one=1 two=2
POST /popa HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 24
Content-Type: application/json
Host: localhost:8080
User-Agent: HTTPie/0.9.9

{
    "one": "1",
    "two": "2"
}

HTTP/1.1 201 Created
Content-Length: 154
content-type: application/json
location: /popa/5972a20d5b31ed7400000001
x-expired-time: 0

{
    "created": "2017-07-22T03:53:33+03:00",
    "group": "popa",
    "id": "5972a20d5b31ed7400000001",
    "meta": {
        "one": "1",
        "two": "2"
    },
    "modified": "2017-07-22T03:53:33+03:00"
}

To get a just created record - we need to use a path from Location header in creation reponse:

$> http -v :8080/popa/5972a2e54396247500000001
GET /popa/5972a2e54396247500000001 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.9


HTTP/1.1 200 OK
Content-Length: 154
content-type: application/json

{
    "created": "2017-07-22T03:53:33+03:00",
    "group": "popa",
    "id": "5972a20d5b31ed7400000001",
    "meta": {
        "one": "1",
        "two": "2"
    },
    "modified": "2017-07-22T03:53:33+03:00"
}

Also, we could get all available records within one group name:

$> http -v :8080/popa
GET /popa HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.9


HTTP/1.1 200 OK
Content-Length: 282
content-type: application/json

[
    {
        "created": "2017-07-22T03:13:35+03:00",
        "group": "popa",
        "id": "597298af0937867200000001",
        "modified": "2017-07-22T03:13:35+03:00"
    },
    {
        "created": "2017-07-22T03:53:33+03:00",
        "group": "popa",
        "id": "5972a20d5b31ed7400000001",
        "meta": {
            "one": "1",
            "two": "2"
        },
        "modified": "2017-07-22T03:53:33+03:00"
    }
]

Or, we can get all data in one object - group -> instances:

$> http -v :8080/
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/0.9.9


HTTP/1.1 200 OK
Content-Length: 426
content-type: application/json

{
    "popa": [
        {
            "created": "2017-07-22T03:13:35+03:00",
            "group": "popa",
            "id": "597298af0937867200000001",
            "modified": "2017-07-22T03:13:35+03:00"
        },
        {
            "created": "2017-07-22T03:53:33+03:00",
            "group": "popa",
            "id": "5972a20d5b31ed7400000001",
            "meta": {
                "one": "1",
                "two": "2"
            },
            "modified": "2017-07-22T03:53:33+03:00"
        }
    ],
    "zuul": [
        {
            "created": "2017-07-22T04:03:26+03:00",
            "group": "zuul",
            "id": "5972a45e4396247500000003",
            "modified": "2017-07-22T04:03:26+03:00"
        }
    ]
}

To update last modified time you could type this:

$> http -v PUT :8080/popa/5972a20d5b31ed7400000001
PUT /popa/5972a20d5b31ed7400000001 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 0
Host: localhost:8080
User-Agent: HTTPie/0.9.9


HTTP/1.1 200 OK
Content-Length: 154
content-type: application/json

{
    "created": "2017-07-22T03:53:33+03:00",
    "group": "popa",
    "id": "5972a20d5b31ed7400000001",
    "meta": {
        "one": "1",
        "two": "2"
    },
    "modified": "2017-07-22T04:10:42+03:00"
}

Why do we want to update last modified time? Luntic can be started with --heartbeat=SECONDS switch, which enables scheduled task for periodical removing expired instances in groups. So, with this switch you need to update modified time, otherwise it removes. By default this scheduled task is disabled.

With PUT method you could also change meta field:

$> http -v PUT :8080/popa/5972a20d5b31ed7400000001 greeting="Hello world" one=1 two=2
PUT /popa/5972a20d5b31ed7400000001 HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 51
Content-Type: application/json
Host: localhost:8080
User-Agent: HTTPie/0.9.9

{
    "greeting": "Hello world",
    "one": "1",
    "two": "2"
}

HTTP/1.1 200 OK
Content-Length: 179
content-type: application/json

{
    "created": "2017-07-22T03:53:33+03:00",
    "group": "popa",
    "id": "5972a20d5b31ed7400000001",
    "meta": {
        "greeting": "Hello world",
        "one": "1",
        "two": "2"
    },
    "modified": "2017-07-22T04:12:16+03:00"
}

And at last, we want to remove the record:

$> http -v DELETE :8080/popa/5972a20d5b31ed7400000001
DELETE /popa/5972a20d5b31ed7400000001 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 0
Host: localhost:8080
User-Agent: HTTPie/0.9.9


HTTP/1.1 204 No Content
Content-Length: 0

Docker

You also are able to use already prepared Docker image:

$> docker run \
    -p 8080:8080 -p 9876:9876 \
    xxlabaza/luntic:1.1.0 \
    --debug --dashboard:9876

API

Registering new service

Creates new record.

Retrieve services

Returns all or specific records on the server.

Update service

This request, first of all, updates modified time field of the updating record.

Remove service

Deletes the service from the services.

Development

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

Prerequisites

For building the project you need only a Nim compiler (Windows or OSX/Unix).

IMPORTANT: Luntic requires Nim version 0.17.0

And, of course, you need to clone Luntic from GitHub:

$> git clone https://github.com/xxlabaza/luntic
$> cd luntic

Building

For building routine automation, I am using config.nims file. It contains all needed tasks described in Nim language.

To build the Luntic project, do the following:

$> nim build
...
Hint: operation successful (52249 lines compiled; 4.124 sec total; 106.934MiB peakmem; Debug Build) [SuccessX]

If you need to build a release (less output binnary file size):

$> nim build release

To check, what everything is fine, type the nex command:

$> build/target/luntic -v
v1.1.0

To build a docker image:

$> nim docker

Running the tests

To run the project's test, do the following:

$> nim test
...
[OK] Parsing request parts

Also, if you build a release, the tests launch automatically.

Built With

Changelog

To see what has changed in recent versions of Luntic, see the changelog file.

Contributing

Please read contributing file for details on my code of conduct, and the process for submitting pull requests to me.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

License

This project is licensed under the Apache License 2.0 License - see the license file for details