README ¶
Ignition Fuel Server
Development and Code style
See https://github.com/golang/go/wiki/CodeReviewComments
The main()
and the package init()
functions are in application.go
. If you are starting to read this code, probably you
will want to start from there.
Install
-
Dependencies
-
Go version 1.9 or above (NOTE: we are currently using 1.9.4)
-
On Ubuntu Xenial or earlier, download and follow instructions from https://golang.org/dl/
-
On Ubuntu Bionic:
sudo apt-get update sudo apt-get install golang-go
-
-
Other dependencies
sudo apt-get update sudo apt-get install golang-goprotobuf-dev git
-
-
Make sure your git config is set, i.e.
git config --global user.name "User Name" git config --global user.email "user@email.com"
-
Make a workspace, for example
mkdir -p ~/go_ws
-
Download server code into new directories in the workspace:
hg clone https://bitbucket.org/ignitionrobotics/ign-fuelserver ~/go_ws/src/bitbucket.org/ignitionrobotics/ign-fuelserver
-
Set necessary environment variable (needs to be set every time the environment is built)
export GOPATH=~/go_ws
-
Install dep tool
Create a bin directory
mkdir ~/go_ws/bin
Move to the workspace's root
cd ~/go_ws
Install dep tool
We're using version 0.4.1 to manage dependencies.
On Ubuntu Bionic, the dep tool will be installed under ~/go_ws/bin (
GOBIN
), so create that:mkdir -p ~/go_ws/bin
export DEP_RELEASE_TAG=v0.4.1 curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
-
Install dependencies
cd ~/go_ws/src/bitbucket.org/ignitionrobotics/ign-fuelserver
Download dependencies into
vendor
folder:# Xenial $GOPATH/bin/dep ensure # Bionic ~/go_ws/bin/dep ensure
Note: this project heavily depends on
ign-go
project. It is recommended to execute the following statement regularly to download the latest version of ign-go.# Xenial $GOPATH/bin/dep ensure -update bitbucket.org/ignitionrobotics/ign-go # Bionic ~/go_ws/bin/dep ensure
-
Make the application
cd ~/go_ws/src/bitbucket.org/ignitionrobotics/ign-fuelserver
go install
-
NOTE: You should not use
go get
to get dependencies (instead usedep ensure
). Usego get
only when you need to modify the source code of any dependency. Alternatively, usevirtualgo
(see "Tips for local development" section below). -
(Optional) Generate a self-signed certificate. Replace
<GO_INSTALL_PATH>
with the path to your golang installation (e.g.:usr/local/go/
:cd ~/go_ws/src
wget https://raw.githubusercontent.com/golang/go/release-branch.go1.8/src/crypto/tls/generate_cert.go
cd ~/go_ws
go run <GO_INSTALL_PATH>/src/generate_cert.go --host localhost --ca true
mv cert.pem key.pem ~/go_ws/src/bitbucket.org/ignitionrobotics/ign-fuelserver/ssl
export IGN_SSL_CERT=~/go_ws/src/bitbucket.org/ignitionrobotics/ign-fuelserver/ssl/cert.pem
export IGN_SSL_KEY=~/go_ws/src/bitbucket.org/ignitionrobotics/ign-fuelserver/ssl/key.pem
Note: to allow self certificates for localhost in Chrome, you need to put this in the chrome address bar :
chrome://flags/#allow-insecure-localhost
-
Install mysql:
NOTE: Install a version greater than v5.6.4. In the servers, we are currently using MySQL v5.7.21
sudo apt-get install mysql-server
The installer will ask you to create a root password for mysql.
-
Create the database and a user in mysql. Replace
'newuser'
with your username and'password'
with your new password:# Xenial mysql -u root -p # Bionic requires sudo sudo mysql -u root -p
CREATE DATABASE fuel;
Also create a separate database to use with tests:
CREATE DATABASE fuel_test;
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON fuel.* TO 'newuser'@'localhost';
FLUSH PRIVILEGES;
exit
-
Create a Test JWT token (this is needed for tests to pass OK --
go test
)TL;DR: Just copy and paste the following env vars in your system (
.env
)# Test RSA256 Private key WITHOUT the -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- # It is used by token-generator to generate the Test JWT Token export TOKEN_GENERATOR_PRIVATE_RSA256_KEY=MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQABAoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5CpuGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0KSu5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aPFaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw== # JWT Token generated by the token-generator program using the above Test RSA keys # This token does not expire. export IGN_TEST_JWT=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXItaWRlbnRpdHkifQ.iV59-kBkZ86XKKsph8fxEeyxDiswY1zvPGi4977cHbbDEkMA3Y3t_zzmwU4JEmjbTeToQZ_qFNJGGNufK2guLy0SAicwjDmv-3dHDfJUH5x1vfi1fZFnmX_b8215BNbCBZU0T2a9DEFypxAQCQyiAQDE9gS8anFLHHlbcWdJdGw # A Test RSA256 Public key, without the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----. # It is used to override the AUTH0_RSA256_PUBLIC_KEY when tests are run. export TEST_RSA256_PUBLIC_KEY=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB
Long version:
Ign Fuel assumes JWT Tokens are RSA256. In order to generate the token, follow these steps:
-
You need to set the
TOKEN_GENERATOR_PRIVATE_RSA256_KEY
env var first. This var is a RSA256 Private key without the-----BEGIN RSA PRIVATE KEY-----
and-----END RSA PRIVATE KEY-----
prefix and suffix. It is used to generate Test JWT Tokens. -
Also please write down the corresponding
TEST_RSA256_PUBLIC_KEY
env var. This var is the RSA256 Public key (without the-----BEGIN CERTIFICATE-----
and-----END CERTIFICATE-----
) that will be used by the backend to validate received Test JWT tokens. NOTE: This one must be the pair of the private keyTOKEN_GENERATOR_PRIVATE_RSA256_KEY
. -
Generate the token:
Build all ign-fuelserver packages and programs:
go install bitbucket.org/ignitionrobotics/ign-fuelserver/...
Note: the
...
instructs Go to build ign-fuelserver and all subpackages (eg. token-generator. You can find the extra packages in cmd/ subfolder).bin/token-generator
-
The token-generator program will output a signed token. You will need to set the
IGN_TEST_JWT
env var with that generated value.
In summary, in order to make
go test
work with JWT you will need to set the following env vars:TOKEN_GENERATOR_PRIVATE_RSA256_KEY
TEST_RSA256_PUBLIC_KEY
IGN_TEST_JWT
-
-
Run the test suite
First, make sure you have all the required env variables set:
export IGN_DB_USERNAME=<DB username>
export IGN_DB_PASSWORD=<DB password>
export IGN_DB_ADDRESS=<DB IP and port. Eg: localhost:3306>
export IGN_DB_NAME=fuel
export IGN_DB_MAX_OPEN_CONNS=66
export IGN_FUEL_RESOURCE_DIR=/tmp/fuel
export IGN_POPULATE_PATH=~/.gazebo/models/
export IGN_TEST_JWT=<JWT token>
export TEST_RSA256_PUBLIC_KEY=< RSA256 public key without the '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----'> Note: TEST_RSA256_PUBLIC_KEY must be able to decode and validate the IGN_TEST_JWT test token.
Then, run all tests:
go test bitbucket.org/ignitionrobotics/ign-fuelserver
-
Run the backend server
First, make sure to set the
AUTH0_RSA256_PUBLIC_KEY
environment variable with the Auth0 RSA256 public key. This env var will be used by the backend to decode and validate any received Auth0 JWT tokens. Note: You can get this key from: https://osrf.auth0.com/.well-known/jwks.json (or from your own auth0 user). Open that url in the browser and copy the value of thex5c
field.$GOPATH/bin/ign-fuelserver
-
Test in the browser
-
If using SSL
https://localhost:4430/1.0/models
-
If not using SSL
http://localhost:8000/1.0/models
-
Permissions
Permission handling is done using the authorization library casbin
To set up the system administrator (root user), export the following environment variable:
export IGN_FUEL_SYSTEM_ADMIN=sys_admin@email.org
Note: when running the tests, this environment variable will be overriden with
a predefined string: root
Environment Variables
You may want to create an .env.bash
file to define environment vars. Remember to add it to .hgignore
.
Then load the env vars using source .env.bash
from the bash terminal where you will run go commands.
Using AWS S3 buckets
- AWS_BUCKET_PREFIX: set it to a prefix that will be shared by all buckets
created by this server (eg.
export AWS_BUCKET_PREFIX=myFuelServer-
) - AWS_BUCKET_USE_IN_TESTS: set it to true if you want to us AWS S3 during tests.
Set to false to use a mock (default: false). (eg.
export AWS_BUCKET_USE_IN_TESTS=true
) - AWS_BUCKET_PREFIX_TEST: if AWS is enabled during tests, set this env var to a
prefix that will be shared by all buckets in tests. (eg.
export AWS_BUCKET_PREFIX_TEST=myFuelServer-tests-
)
Flagging content and sending emails
To enable flagging of content you need to set the following env vars:
-
AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
-
IGN_FLAGS_EMAIL_FROM: The email address used as
from
when sending email notifications. -
IGN_FLAGS_EMAIL_TO: The email address used as
to
when sending email notifications.
Database
There are three databases in use:
-
ign-fuel: a production database for use with the production Elastic Beanstalk environment,
-
ign-fuel-staging: a staging database for use with the staging Elastic Beanstalk environment, and
-
ign-fuel-integration: an integration database for use with the integration Elastic Beanstalk environment.
The production database should never be manually altered. The staging database should match the production environment, and the purpose is to catch migration errors on the staging Elastic beanstalk instance. The integration database is used during testing and development. This database is frequently wiped and altered.
Environment variables
IGN_DB_USERNAME
: Mysql user name.IGN_DB_PASSWORD
: Mysql user password.IGN_DB_ADDRESS
: Mysql address, of the formhost:port
.IGN_DB_NAME
: Mysql database name, which should befuel
.IGN_DB_MAX_OPEN_CONNS
: Max number of open connections in connections pool. Eg. 66.IGN_FUEL_RESOURCE_DIR
: the file system path where models will be stored.IGN_FUEL_VERBOSITY
: controls the level of output, with a default value of 2. 0 = critical messages, 1 = critical & error messages, 2 = critical & error & warning messages, 3 = critical & error & warning & informational messages, 4 = critical & error & warning & informational & debug messagesAUTH0_RSA256_PUBLIC_KEY
: Auth0 RSA256 public key without the '-----BEGIN CERTIFICATE-----' and '-----END CERTIFICATE-----' Note: You can get this key from: https://osrfoundation.auth0.com/.well-known/jwks.json (or from your auth0 user). It is the "x5c" field.
Leaderboards
There may be some cases where scores for specific organizations or circuits
should not be displayed in competition leaderboards. There are environment
variables available to control which organizations and circuits should not be
displayed in leaderboards. These environment variables do not stop scores from
being produced, they only filter /subt/leaderboard
results.
IGN_FUEL_TEST_ORGANIZATIONS
List of organizations to filter from leaderboard scores.IGN_FUEL_HIDE_CIRCUIT_SCORES
List of circuits to filter from leaderboard scores.
All of these environment variables can contain multiple comma-separated values.
Testing and Development
-
IGN_POPULATE_PATH
: Path to a set of Gazebo models. Setting this variable will populate the database with these models. -
IGN_TEST_JWT
: A JWT token used from unit tests. Note: theTEST_RSA256_PUBLIC_KEY
must be able to decode and validate this test token. -
TEST_RSA256_PUBLIC_KEY
: if present, override the Auth0 public RSA key with this test key. This one must match with the Test JWT token. It is used by unit tests (go test
). -
TOKEN_GENERATOR_PRIVATE_RSA256_KEY
: RSA 256 private key Used by the Token Generator utility program to generate the Test JWT token. It must pair with theTEST_RSA256_PUBLIC_KEY
public key.
Naming conventions
In general we will try to follow Go naming conventions. In addition, these are own conventions:
-
For constructors / factory-methods we will use the form:
New<object>
. See: http://www.golangpatterns.info/object-oriented/constructors -
For HTTP POST handlers we use:
<object>Create
. eg: ModelCreate. -
For HTTP DELETE handlers we use:
<object>Remove
. eg: ModelRemove. -
An HTTP handler that returns a collection will have the form:
<object>List<format>
. eg: ModelListJSON. Note:format
is optional. JSON will be assumed by default. -
An HTTP handler that returns a single element will be:
<object>Index<format>
. eg: ModelIndexZip. Note:format
is optional. JSON will be assumed by default. -
For HTTP OPTIONS handler we use:
<object>API
. -
We use the func suffix
Impl
when we delegate implementation of a handler to an internal function. Eg: UserCreate handler can delegate to userCreateImpl.
Linter
-
Get the linter
cd ~/go_ws
go get -u golang.org/x/lint/golint
-
Run the linter
./bin/golint $(go list bitbucket.org/ignitionrobotics/ign-fuelserver/...) | grep -v .pb.go
Note you can create this bash script:
#!/bin/bash
go get -u golang.org/x/lint/golint
$GOPATH/bin/golint $(go list bitbucket.org/ignitionrobotics/ign-fuelserver/...) | grep -v .pb.go
Proto
-
If you need to modify the proto files then you will need to run (from the proto folder):
protoc --go_out=. *.proto
Then update the generated import proto from code.google... to "github.com/golang/protobuf/proto"
Coverage
-
Run test suite with coverage enabled
go test -cover bitbucket.org/ignitionrobotics/ign-fuelserver
-
Tip. Add this function to your ~/.bashrc
cover () {
t="/tmp/go-cover.$$.tmp"
go test -covermode=count -coverprofile=$t $@ && go tool cover -html=$t && unl$
}
Then run the function from your project folder. Tests will be run and a browser window will open with coverage results.
Integration deployment
If it's the first time that you deploy on integration
:
-
Install eb CLI tool (if needed).
-
Configure eb:
eb init
And choose the following options:
-
Select
us-east-1
as region. -
Select
ign-fuel-server
as the application name. -
Select
ign-fuel-server-integration
as the environment name.
-
Otherwise, just type:
eb deploy
Staging/Production deployment
The staging
and production
branches push code through bitbucket
pipelines to AWS Elastic Beanstalk (EBS).
-
Push code to staging. Make sure pipelines completes successfully.
-
Test
staging.api.ignitionfuel.org
-
When ready, Swap Environment URLs with the production EBS environment.
-
Merge the
staging
branch into theproduction
branch, and push. -
Test
staging.api.ignitionfuel.org
again -
Swap the EBS environment URLs back.
AWS Configuration
-
Elastic Beanstalk runs go in a docker container
-
AWS Relation Database (RDS) runs an instance of mysql.
-
Each EC2 instance started by EBS mounts an NFS filesystem, via Elastic Filesystem, on
/fuel
. This filesystem store all the mercurial repositories.
AWS RDS
There are two mysql databases hosted on Amazon.
-
ign-fuel
: The production database.- Endpoint: ign-fuel.cpznmiopbczj.us-east-1.rds.amazonaws.com:3306
-
ign-fuel-dev
: The development and testing database. You can write tests that will run on bitbucket pipelines against this database. Make sure to clean the database up after each test.- Endpoint: ign-fuel-dev.cpznmiopbczj.us-east-1.rds.amazonaws.com:3306
Development
See the Database section above for information on the different database options.
Transactions
Try to create and commit transactions within main Handlers, and not in the helper functions.
REST Documentation
Swagger is used to document the REST API. This includes both model and route information.
Do not manually edit swagger.json
Process
-
Document a route or model following this documentation.
-
Install swagger inside your
GOPATH
- go get -u github.com/go-swagger/go-swagger/cmd/swagger
- go install github.com/go-swagger/go-swagger/cmd/swagger
-
Generate the
swagger.json
file. This file will be used by a webserver to display the API documentation../bin/swagger generate spec -o ./src/bitbucket.org/ignitionrobotics/ign-fuelserver/swagger.json -b ./src/bitbucket.org/ignitionrobotics/ign-fuelserver/ -m
-
Commit and push your changes to the repository.
-
View the results at http://doc.ignitionfuel.org. Enter a new
swagger.json
in theExplore
box to see a different version of the API.
Useful links
- This page documents how to write swagger documentation that will be parsed to generate the swagger.json file.
- This is an instance of swagger-ui, where the
index.html
file was edited to point to our swagger file.
Log Files
Two web services are used for log management.
- rollbar.com
Rollbar aggregates log messages from the application. Application log
messages are sent to rollbar when a REST error is returned to a client or by
using one of ign.Debug
, ign.Info
, ign.Warning
, ign.Error
, or
ign.Critical
.
Messages are sent to rollbar asynchronously. This could result in messages
appearing out of order on rollbar's UI. In addition to the timestamp
generated by rollbar upon message arrival, rollbar keeps
a metadata.customer_timestamp
which should be the application's timestamp.
You can use the RQL console with metadata.custom_timestamp
to reorder
items. Steps:
1. Click on `RQL` in rollbar's top toolbar.
2. Enter an SQL query like the following:
```
SELECT *
FROM item_occurrence
WHERE item.counter = 932
ORDER BY metadata.customer_timestamp DESC
LIMIT 0, 20
```
3. Click 'Run'
- papertrail.com
Papertrail aggregates system log messages. Log file upload to Papertrail
happens automatically. Configuration, including specification of system log
files to monitor, is handled in
.ebextensions/remote_syslog.ebextensions.config
.
Debugging inside docker container
If you ever need to debug the application as if it were running in AWS or the pipelines, you need to do it from inside its docker containter. To do that:
Most ideas taken from here: Mysql and Docker https://docs.docker.com/samples/library/mysql/#-via-docker-stack-deploy-or-docker-compose
-
First create the docker image for the ign-fuelserver.
docker build ign-fuelserver
. Write down its image ID. -
Then run a dockerized mysql database.
docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=<desired-root-pwd> -d mysql:5.7.21
This will create a mysql docker container with an empty mysql in it. -
Then you need to connect to that mysql container instance to run commands:
docker exec -it my-mysql bash
. From inside the container, connect to mysql using the client (eg.mysql -u root -p
) and create databases fuel and fuel_test. eg:create database fuel_test;
. -
Run the ign-fuelserver docker and link it to mysql database.
docker run --name ign-fuelserver --rm --link my-mysql:mysql -ti <fuelserver-image-id> /bin/bash
-
Then from inside the server container you need to set the Env Var that points to the linked docker mysql. eg.
export IGN_DB_ADDRESS="172.17.0.2:3306"
After that you can source your env vars and run commands such as go test
.
Tips for local development using multiple dependent projects
This is useful when you need to test uncommitted changes from a project depedency. Eg. when you need to test changes in ign-go using ign-fuelserver.
Install vg (virtualgo
) . This tool is used on top of go dep
: https://github.com/GetStream/vg
First, initialize vg support in your system. In a terminal, run:
export PATH=$PATH:$GOPATH/bin && eval "$(vg eval --shell bash)"
Tip: I have pushed a .vgenable script that can be sourced
later to enable vg support in current terminal. Eg. source .vgenable
How to use vg:
-
vg init
(only the first time, to initialize the project with vg) -
vg ensure
(this command delegates todep ensure
and then removes thevendor
folder) -
To add or update dependencies (into Gopck.toml) use:
vg ensure -- -update <dependency>
(or just use normaldep ensure -update <dependency>
style, and later runvg ensure
to move dependencies into vg's workspace) -
How to switch to a local version of a dependency: eg.
vg localInstall bitbucket.org/ignitionrobotics/ign-go
Documentation ¶
Overview ¶
Package main Ignition Fuel Server RESET API
This package provides a REST API to the Ignition Fuel server.
Schemes: https Host: staging-api.ignitionfuel.org BasePath: /1.0 Version: 0.1.0 License: Apache 2.0 Contact: info@openrobotics.org
swagger:meta go:generate swagger generate spec
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
bundles
|
|
cmd
|
|
Package fuel is a generated protocol buffer package.
|
Package fuel is a generated protocol buffer package. |