This generated README.md file loosely follows a popular template.
One paragraph of project description goes here.
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
Install go dep
go get -u github.com/golang/dep/cmd/dep
Install atlas-db-controller for managing database resources
- To create atlas-db custom resource and controller follow link. Make sure to create one if not already exists.
- To create database server instance, database and schema/tables resources locally to be used by contacts app, follow
export GIT_USER=<YOUR_GIT_USER_NAME>
export GIT_TOKEN=<YOUR_GIT_USER_TOKEN>
cat deploy/contacts-localdb.yaml | envsubst '$GIT_USER$GIT_TOKEN' | kubectl apply -f -
To create GIT_TOKEN if not exists follow link
- To use RDS database instance, database and schema/tables resources used by contacts app, modify
contacts-rds.yaml
and run"
kubectl create -f ./deploy/contacts-rds.yaml
Please note that you should have the following ports opened on you local workstation: :8080 :8081 :9090 :5432
.
If they are busy - please change them via corresponding parameters of gateway
and server
binaries or postgres container run.
Run PostgresDB:
docker run --name contacts-db -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=contacts -p 5432:5432 -d postgres:9.4
Table creation should be done manually by running the migrations scripts. Scripts can be found at ./db/migrations/
Create vendor directory with required golang packages
make vendor
Run App server:
go run ./cmd/server/*.go -db "host=localhost port=5432 user=postgres password=postgres sslmode=disable dbname=contacts"
For Multi-Account environment, Authorization token (Bearer) is required. You can generate it using https://jwt.io/ with following Payload:
{
"AccountID": YourAccountID
}
Example:
{
"AccountID": 1
}
Bearer
export JWT="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBY2NvdW50SUQiOjF9.GsXyFDDARjXe1t9DPo2LIBKHEal3O7t3vLI3edA7dGU"
Request examples:
curl -H "Authorization: Bearer $JWT" \
http://localhost:8080/v1/contacts -d '{"first_name": "Mike", "primary_email": "[email protected]"}'
curl -H "Authorization: Bearer $JWT" \
http://localhost:8080/v1/contacts -d \
'{"first_name": "Robert", "primary_email": "[email protected]", "nicknames": ["bob", "robbie"]}'
curl -H "Authorization: Bearer $JWT" \
http://localhost:8080/v1/contacts?_filter='first_name=="Mike"'
Note, that JWT
should contain AccountID field.
make
Will be created docker images 'infoblox/contacts-gateway' and 'infoblox/contacts-server'.
If this process finished with errors it's likely that docker doesn't allow to mount host directory in its container.
Therefore you are proposed to run su -c "setenforce 0"
command to fix this issue.
Make sure nginx is deployed in your K8s. Otherwise you can deploy it using
make nginx-up
To deploy atlas-contacts-app use
make up
Will be used latest Docker Hub images: 'infoblox/contacts-gateway:latest', 'infoblox/contacts-server:latest'.
To deploy authN stub, clone atlas-stubs repo (https://github.com/infobloxopen/atlas-stubs.git) and then execute deployment script inside authn-stub package or:
curl https://raw.githubusercontent.com/infobloxopen/atlas-stubs/master/authn-stub/deploy/authn-stub.yaml | kubectl apply -f -
This will start AuthN stub that maps User-And-Pass
header on JWT tokens, with following meaning:
admin1:admin -> AccountID=1
admin2:admin -> AccountID=2
Try it out by executing following curl commands:
# Create some profiles
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/profiles -d '{"name": "personal", "notes": "Used for personal aims"}' | jq
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/profiles -d '{"name": "work", "notes": "Used for work aims"}' | jq
# Create some groups assigned to profiles
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/groups -d '{"name": "schoolmates", "profile_id": 1}' | jq
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/groups -d '{"name": "family", "profile_id": 1}' | jq
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/groups -d '{"name": "accountants", "profile_id": 2}' | jq
# Add some contacts assigned to profiles and groups
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/contacts -d '{"first_name": "Mike", "primary_email": "[email protected]", "profile_id": 1, "groups": [{"id": 1, "name": "schoolmates", "profile_id": 1}, {"id": 2, "name": "family", "profile_id": 1}], "home_address": {"city": "Minneapolis", "state": "Minnesota", "country": "US"}}' | jq
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/contacts -d '{"first_name": "John", "primary_email": "[email protected]", "profile_id": 2, "work_address": {"city": "St.Paul", "state": "Minnesota", "country": "US"}}' | jq
# Read created resources
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/profiles | jq
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/groups | jq
curl -k -H "User-And-Pass: admin1:admin" \
https://$(minikube ip)/atlas-contacts-app/v1/contacts | jq
DISCLAIMER: it is intended only for demonstration purposes and should not be emulated.
Contacts App implements pagination in by adding application specific page token implementation.
Actually the service supports "composite" pagination in a specific way:
-
limit and offset are still supported but without page token
-
if an user requests page token and provides limit then limit value will be used as a step for all further requests
page_token = null & limit = 2 -> page_token=base64(offset=2:limit=2)
-
if an user requests page token and provides offset then only first time the provided offset is applied
page_token = null & offset = 2 & limit = 2 -> page_token=base64(offset=4:limit=2)
Get all contacts: GET http://localhost:8080/v1/contacts
{
"results": [
{
"emails": [
{
"address": "[email protected]",
"id": "1"
}
],
"first_name": "Mike",
"id": "1",
"primary_email": "[email protected]"
},
{
"emails": [
{
"address": "[email protected]",
"id": "2"
}
],
"first_name": "Mike",
"id": "2",
"primary_email": "[email protected]"
},
{
"emails": [
{
"address": "[email protected]",
"id": "3"
}
],
"first_name": "Mike",
"id": "3",
"primary_email": "[email protected]"
}
],
"success": {
"status": 200,
"code": "OK"
}
}
Default pagination (supported by atlas-app-toolkit): GET http://localhost:8080/v1/contacts?_limit=1&_offset=1
{
"results": [
{
"emails": [
{
"address": "[email protected]",
"id": "2"
}
],
"first_name": "Mike",
"id": "2",
"primary_email": "[email protected]"
}
],
"success": {
"status": 200,
"code": "OK"
}
}
Request specific page token: GET http://localhost:8080/v1/contacts?_page_token=null&_limit=2
{
"results": [
{
"emails": [
{
"address": "[email protected]",
"id": "1"
}
],
"first_name": "Mike",
"id": "1",
"primary_email": "[email protected]"
},
{
"emails": [
{
"address": "[email protected]",
"id": "2"
}
],
"first_name": "Mike",
"id": "2",
"primary_email": "[email protected]"
}
],
"success": {
"status": 200,
"code": "OK",
"_page_token": "NDo0"
}
}
Get next page via page token: GET http://localhost:8080/v1/contacts?_page_token=NDo0
{
"results": [
{
"emails": [
{
"address": "[email protected]",
"id": "3"
}
],
"first_name": "Mike",
"id": "3",
"primary_email": "[email protected]"
}
],
"success": {
"status": 200,
"code": "OK",
"_page_token": "NTo0"
}
}
Get next page: GET http://localhost:8080/v1/contacts?_page_token=NTo0
The "_page_token": "null"
means there are no more pages
{
"success": {
"status": 200,
"code": "OK",
"_page_token": "null"
}
}
Add additional notes about how to deploy this application. Maybe list some common pitfalls or debugging strategies.
Explain how to run the automated tests for this system.
Give an example
We use SemVer for versioning. For the versions available, see the tags on this repository.