To run traffic_ops_golang
proxy locally the following prerequisites are needed:
We treat golang.org/x
as apart of the Go compiler so that means that we still vendor application dependencies for stability and reproducible builds. This is a helpful tool for managing dependencies https://github.com/govend/govend
To download the remaining golang.org/x
dependencies you need to:
$ go get -v
To run the Golang proxy locally the following represents a typical sequence flow. /api/1.2 will proxy through to Mojo Perl. /api/1.3 will serve the response from the Golang proxy directly and/or interact with Postgres accordingly.
/api/1.2 routes:
TO Golang Proxy (port 8443)
<-->TO Mojo Perl
<-->TO Database (Postgres)
/api/1.3 routes:
TO Golang Proxy (port 8443)
<-->TO Database (Postgres)
=======================================
Copy traffic_ops/app/conf/cdn.conf
to $HOME/cdn.conf
so you can modify it for development purposes.
$HOME/cdn.conf
"traffic_ops_golang" : { "port" : "443",
"traffic_ops_golang" : { "port" : "8443",
=======================================
By default /var/log/traffic_ops/error.log
is configured for output, to change this modify your $HOME/cdn.conf
for the following:
$HOME/cdn.conf
"traffic_ops_golang" : { "..." "log_location_error": "stdout", "log_location_warning": "stdout", "log_location_info": "stdout", "log_location_debug": "stdout", "log_location_event": "stdout", ... }
Go is a compiled language so any local changes will require you to CTRL-C the console and re-run the traffic_ops_golang
Go binary locally:
go build && ./traffic_ops_golang -cfg $HOME/cdn.conf -dbcfg ../app/conf/development/database.conf
Traffic Ops is moving to Go! You can help!
We're in the process of migrating the Perl/Mojolicious Traffic Ops to Go. This involves converting each route, one-by-one. There are many small, simple routes, like /api/1.2/regions
and api/1.2/divisions
. If you want to help, you can convert some of these.
You‘ll need at least a basic understanding of Perl and Go, or be willing to learn them. You’ll also need a running Traffic Ops instance, to compare the old and new routes and make sure they're identical.
If you don‘t already have an endpoint in mind, open TrafficOpsRoutes.pm and browse the routes. Start with /api/
routes. We’ll be moving others, like config files, but they‘re a bit more complex. We specifically won’t be moving GUI routes (e.g. /asns
), they'll go away when the new Portal is done.
After you pick a route, you‘ll need to look at the code that generates it. For example, if we look at $r->get("/api/$version/cdns")->over( authenticated => 1, not_ldap => 1 )->to( 'Cdn#index', namespace => $namespace );
, we see it’s calling Cdn#index
, so we look in app/lib/API/Cdn.pm
at sub index
.
As you can see, this is a very simple route. It queries the database CDN
table, and puts the id
, name
, domainName
, dnssecEnabled
, and lastUpdated
fields in an object, for every database entry, in an array.
If you go to /api/1.2/cdns
in a browser, you'll see Perl is also wrapping it in a "response"
object.
Go
Now we need to create the Go endpoint.
Open routes.go. Routes are defined in the Routes
function, of the form {version, method, path, handler}
. Notice the path can contain variables, of the form /{var}/
. These variables will be made available to your handler.
The first step is to create your handler. For an example, look at monitoringHandler
in monitoring.go
. Your handler arguments can be any data available to the router (the config and database, or what you can create from them). Passing the db
or prepared Stmt
s is common. The handler function must return a RegexHandlerFunc
. In general, you want to return an inline function, return func(w http.ResponseWriter, r *http.Request, p ParamMap) {...
.
The ResponseWriter
and Request
are standard Go HandlerFunc
parameters. The ParamMap
is a map[string]string
, containing the variables from your route path.
Now, your handler just needs to load the data, format it, and write it to the ResponseWriter
, like any other Go HandlerFunc
.
This is the hard part, where you have to recreate the Perl response. But it‘s all standard Go programming, reading from a database, creating JSON, and writing to the http.ResponseWriter
. If you’re just learning Go, look at some of the other endpoints like monitoring.go
, and maybe google some Golang tutorials on SQL, JSON, and HTTP. The Go documentation is also helpful, particularly https://golang.org/pkg/database/sql/ and https://golang.org/pkg/encoding/json/.
Your handler should be in its own file, where you can create any structs and helper functions you need.
Back to routes.go
, you need to add your handler to the Routes
function. For example, /api/1.2/cdns
would look like {1.2, http.MethodGet, "cdns", wrapHeaders(wrapAuth(cdnsHandler(d.DB), d.Insecure, d.TOSecret, rd.PrivLevelStmt, CdnsPrivLevel))},
.
The only thing we haven‘t talked about are those wrap
functions. They each take a RegexHandlerFunc
and return a RegexHandlerFunc
, which lets them ‘wrap’ your handler. You almost certainly need both of them; if you’re not sure, ask on the mailing list or Slack. You'll notice the wrapAuth
function also takes config parameters, as well as a PrivLevel
. You should create a constant in your handler file of the form EndpointPrivLevel
and pass that. If your endpoint modifies data, use PrivLevelOperations
, otherwise PrivLevelReadOnly
.
That‘s it! Test your endpoint, read Contributing.md if you haven’t, and submit a pull request!
If you have any trouble, or suggestions for this guide, hit us up on the mailing list or Slack.