This is a technical challenge for Canonical's snap team. The API can be looked at in a glace by visiting these docs.
The cmd
directory holds the entrypoint for the program. This folder's contents were generated by the goswagger
code
generator.
The configure
directory contains code required to configure the service. This code runs before the service is
considered active. It sets things up like a logger and the backend assets.
The endpoints
directory is where the business logic of the service resides. These functions are triggered when an
incoming request reaches out to an endpoint. The function is responsible for taking the data in the incoming request,
talking to the backend code, and returning a normal or error response.
The models
directory contains the data structures that are specified in the swagger.yml
. These data structures are
how this server and its clients communicate. Its contents were generated by the goswagger
code generator.
The restapi
directory contains the majority of generated code logic. These are things like, serving the API's visual
interface, input validation, routing, etc. Its contents were generated by the goswagger
code generator except for one
special file. This special file is located at restapi/configure_snap_api_challenge.go
. This file is hand edited to
allow for configuration, setting endpoint handlers, and middleware.
The Caddyfile
file is used to tell Caddy how to route traffic. Currently, the only
instruction is to serve as a reverse proxy to the snapapi
container, but it also serves as a TLS termination point in
production.
The docker-compose.yml
file is used to organize the containers for this service. It directs Docker images, persistent
storage, port forwarding, and allows for administration via the docker-compose
command.
The Dockerfile
file is used to create a Docker image for the service. This Dockerfile
is a two stage Dockerfile
with the first stage building the code, and the second stage image only containing the binary and required
configurations.
The swagger.yml
file is used to describe the service. It specifies the endpoints, their parameters, and their
responses. It is fed into the goswagger
code generator to generate the server (and client) stubs for the service. The
swagger.yml
is a useful way to communicate how to interact with the service as it is a standardized and widely
supported format.
This service used the github.com/mvo5/qrest-skeleton/backend
Go package as an external dependency. I did not change or
add to any of the mock backend code.
This service's generated API documentation is hosted live at https://snapapi.micahparks.com/api/v0/docs. It can be used to understand the service better, generate requests, etc.
This service defaults resource limits to zero.
This service will not allow a quota-group to be added as a member to another quota-group if it is not already present in the quota manager.
This service was designed with bulk transactions in mind. All endpoints consume JSON that allows for the querying or manipulation of multiple quota-groups and/or members at once.
This service was designed as a containerized microservice using Docker.
This service is hosted live at snapapi.micahparks.com. It uses the image at micahparks/snapapi
and snippets from this
repo's docker-compose.yml
and Caddyfile
.
This service has a rate limiter middleware that allows for up to 1 request per second.
There repo has a couple TODO
s which suggest improvements for the service. Most of these are listed below as well.
Running the code on your local machine can take two forms. You may either use the go
tool to compile and run, or use
docker-compose
.
HOST=0.0.0.0 PORT=30000 go run cmd/snap-api-challenge-server/main.go
(This will use plaintext HTTP and use
port 30000
.)
docker-compose up
(This will create a self-signed certificate and use ports 80
and 443
.)
Testing is essential for any service. However, this service is a challenge and loosely time-boxed. I chose to not implement any formal tests for this service due to time.
However, there are two files, exampleCurl.local.sh
and exampleCurl.sh
that I quickly wrote to show that the service
will perform what's expected of it in challenge.pdf
's example. If you run the exampleCurl.sh
script on an internet
connected computer with curl
installed, it will bring the live deployed service on the public internet to the state
described in the example. If you run the service locally with the instructions under
Compiled with environment variables
, the exampleCurl.local.sh
script will do the same to your local service.
- Write Postman tests and Go tests utilizing
httptest
,gocheck
, etc. - Implement the usage portion in the backend.
- Add more logic to rate limiter middleware.
- More debug logging.
- Add a logging middleware.
- Use non-developer zap logger.