A Port domain API service to store and retrieve ports.
Each port looks in JSON like:
{
"name": "Djibouti",
"city": "Djibouti",
"country": "Djibouti",
"alias": [],
"regions": [],
"coordinates": [
43.1456475,
11.5720765
],
"province": "Djibouti",
"timezone": "Africa/Djibouti",
"unlocs": [
"DJJIB",
"DJPOD"
],
"code": "77701"
}
So the port may have many "unlocs": ["DJJIB", "DJPOD"]
and we need a deduplication by the unloc code.
The repo contains:
- ports-service - a REST-like API service to save and get a port.
- ports-import tool to load ports from JSON file e.g.
ports.json
.
They both can be configured with a config.json file e.g. DB settings, API listen address etc.
Sample of API. Create/update a port with POST:
POST http://localhost:8080/api/v1/ports/
Authorization: Basic api secret
Content-Type: application/json
{
"name": "Ajman",
"unlocs": [
"AEAJM"
]
}
Get/retrieve with GET:
GET http://localhost:8080/api/v1/ports/?unloc=AEAJM
Authorization: Basic api secret
Currently, for the API only HTTP is supported so use a reverse proxy. You can configure a basic authorization for the API.
The service use PostgreSQL with JSON columns support.
It's database can be initialized with init.sql
file.
The provided docker-compose uses an official PostgreSQL image with the init.sql script.
Use docker-compose up
and docker-compose down
to start and stop the application.
Default configuration is:
{
"DatabaseUrl": "postgres://postgres:postgres@db:5432/portsdb?search_path=ports_schema",
"PortsFilePath": "ports.json",
"ListenAddr": ":8080",
"Credentials": {
"api": "secret"
}
}
DatabaseUrl
: can bemem://
for in memory or a full PostgreSQL connection string.PortsFilePath
: used only by importer to specify a ports.json file path.ListenAddr
: bind address for HTTP APICredentials
: a username/password pairs for API's basic auth.
Note: passwords aren't hashed, autogenerate them. Also remove the default password on a production.
You can override config options like DB URL in the config.local.json
.
For Goland run configuration were added.
The requests.http
file contains samples of API requests.
Or you can run make build
and then docker-compose up
. The docker compose will build an image.
The default target for make is to build a docker image ports-service:latest
.
The image also contain the importer in /opt/posrts-importer
so you can execute it in interactive mode.
To run a linter execute make run-lint
.
You may need to install a linter sudo snap install golangci-lint
.
You can build manually with:
go build -o ports-import ./cmd/import
go build -o ports-service ./cmd/service
- Given a file with ports data (ports.json), write a port domain service that either creates a new record in a database, or updates the existing one (Hint: no need for delete or other methods).
- The file is of unknown size, it can contain several millions of records, you will not be able to read the entire file at once.
- The service has limited resources available (e.g. 200MB ram).
- The end result should be a database containing the ports, representing the latest version found in the JSON. (Hint: use an in memory database to save time and avoid complexity).
- A Dockerfile should be used to contain and run the service (Hint: extra points for avoiding compilation in docker).
- Provide at least one example per test type that you think are needed for your assignment. This will allow the reviewer to evaluate your critical thinking as well as your knowledge about testing.
- Your readme.md should explain how to run your program and test it.
- The service should handle certain signals correctly (e.g. a TERM or KILL signal should result in a graceful shutdown).
- Address security concerns for Docker
- Database in docker container
- Docker-compose file