Skip to content

Commit

Permalink
Convert Traffic Ops into a Service Oriented architecture(SOA) product (
Browse files Browse the repository at this point in the history
…apache#6754)

* initial changes

* working changes

* formatting and cleanup

* cleanup

* adding log handlers

* add dcos, cleanup

* add todos

* add todos

* cleanup config

* add insecure option to backend config

* Adding proper log handlers

* remove priv level from backend config

* code review first pass

* code review fixes final

* change log call

* change mutex type

* addressing code review comments

* change regex handling
  • Loading branch information
srijeet0406 committed Oct 2, 2022
1 parent 5a04033 commit 8a5e532
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Replaces all Traffic Portal Tenant select boxes with a novel tree select box [#6427](https://github.com/apache/trafficcontrol/issues/6427).
- Traffic Monitor: Add support for `access.log` to TM.
- Added functionality for login to provide a Bearer token and for that token to be later used for authorization.
- [Traffic Ops] Added support for backend configurations so that Traffic Ops can act as a reverse proxy for these services [#6754](https://github.com/apache/trafficcontrol/pull/6754).
- Added functionality for CDN locks, so that they can be shared amongst a list of specified usernames.
- [Traffic Ops | Traffic Go Clients | T3C] Add additional timestamp fields to server for queuing and dequeueing config and revalidate updates.
- Added layered profile feature to 4.0 for `GET` /servers/, `POST` /servers/, `PUT` /servers/{id} and `DELETE` /servers/{id}.
Expand Down
34 changes: 32 additions & 2 deletions docs/source/admin/traffic_ops.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
***********
Traffic Ops
***********
Traffic Ops is quite possible the single most complex and most important Traffic Control component. It has many different configuration options that affect a wide range of other components and their interactions.
Traffic Ops is quite possibly the single most complex and most important Traffic Control component. It has many different configuration options that affect a wide range of other components and their interactions.

.. _to-install:

Expand Down Expand Up @@ -257,7 +257,7 @@ While this section contains instructions for running Traffic Ops manually, the o

traffic_ops_golang
------------------
``traffic_ops_golang [--version] [--plugins] [--api-routes] --cfg CONFIG_PATH --dbcfg DB_CONFIG_PATH [--riakcfg RIAK_CONFIG_PATH]``
``traffic_ops_golang [--version] [--plugins] [--api-routes] --cfg CONFIG_PATH --dbcfg DB_CONFIG_PATH [--riakcfg RIAK_CONFIG_PATH] [--backendcfg BACKEND_CONFIG_PATH]``

.. option:: --cfg CONFIG_PATH

Expand All @@ -282,6 +282,10 @@ traffic_ops_golang

.. impl-detail:: The name of this flag is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.

.. option:: --backendcfg BACKEND_CONFIG_PATH

This optional command line flag specifies the absolute or relative path to a configuration file used by Traffic Ops to act as a reverse proxy and forward requests on the specified paths to the corresponding hosts - `backends.conf`_

.. option:: --version

Print version information and exit.
Expand Down Expand Up @@ -586,6 +590,32 @@ This file sets authentication options for connections to Riak when used as the T

.. impl-detail:: The name of this file is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.

backends.conf
"""""""""""""
This file deals with the configuration parameters of running Traffic Ops as a reverse proxy for certain endpoints that need to be served externally by other backend services. It is a JSON-format set of options and their respective values. `traffic_ops_golang`_ will use whatever file is specified (if any) by its :option:`--backendcfg` option. The keys of the file are described below.

:routes: This is an array of options to configure Traffic Ops to forward requests of specified types to the appropriate backends.

:path: The regex matching the endpoint that will be served by the backend, for example, :regexp:`^/api/4.0/foo?$`.
:method: The HTTP method for the above mentioned path, for example, ``GET`` or ``PUT``.
:routeId: The integral identifier for the new route being added.
:hosts: An array of the host object, which specifies the protocol, hostname and port where the request (if matched) needs to be forwarded to.

:protocol: The protocol/scheme to be followed while forwarding the requests to the backend service.
:hostname: The hostname of the server where the backend service is running.
:port: The port (integer) on the backend server where the service is running.

:insecure: A boolean specifying whether or not TO should verify the backend server's certificate chain and host name. This is not recommended for production use. This is an optional parameter, defaulting to ``false`` when not present.
:permissions: An array of permissions (strings) specifying the permissions required by the user to use this API route.
:opts: A collection of key value pairs to control how the requests should be forwarded/ handled, for example, ``"alg": "roundrobin"``. Currently, only ``roundrobin`` is supported (which is also the default if nothing is specified) by Traffic Ops.

Example backends.conf
'''''''''''''''''''''
.. include:: ../../../traffic_ops/app/conf/backends.conf
:code: json
:tab-width: 4


Installing the SSL Certificate
------------------------------
By default, Traffic Ops runs as an SSL web server (that is, over HTTPS), and a certificate needs to be installed.
Expand Down
52 changes: 52 additions & 0 deletions traffic_ops/app/conf/backends.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"routes": [
{
"path": "^/api/4.0/foo?$",
"method": "GET",
"hosts": [
{
"protocol": "https",
"hostname": "localhost",
"port": 8444
},
{
"protocol": "https",
"hostname": "localhost",
"port": 8445
}
],
"insecure": true,
"permissions": [
"CDN:READ"
],
"routeId": 123456,
"opts": {
"alg": "roundrobin"
}
},
{
"path": "^/api/4.0/foos?$",
"method": "GET",
"hosts": [
{
"protocol": "https",
"hostname": "localhost",
"port": 8444
},
{
"protocol": "https",
"hostname": "localhost",
"port": 8445
}
],
"insecure": true,
"permissions": [
"CDN:READ"
],
"routeId": 123457,
"opts": {
"alg": "roundrobin"
}
}
]
}
3 changes: 3 additions & 0 deletions traffic_ops/app/conf/production/backends.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"routes": [],
}
2 changes: 1 addition & 1 deletion traffic_ops/etc/init.d/traffic_ops
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ start ()
stop
echo -e "Starting Traffic Ops\n"
ulimit -n 200000 || echo "Setting ulimit max files failed for traffic_ops_golang"
cd $TO_DIR && $TO_DIR/bin/traffic_ops_golang -cfg $TO_DIR/conf/cdn.conf -dbcfg $TO_DIR/conf/production/database.conf -riakcfg $TO_DIR/conf/production/riak.conf &
cd $TO_DIR && $TO_DIR/bin/traffic_ops_golang -cfg $TO_DIR/conf/cdn.conf -dbcfg $TO_DIR/conf/production/database.conf -riakcfg $TO_DIR/conf/production/riak.conf -backendcfg $TO_DIR/conf/production/backends.conf &
}

stop ()
Expand Down
54 changes: 54 additions & 0 deletions traffic_ops/traffic_ops_golang/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,35 @@ import (
"github.com/apache/trafficcontrol/lib/go-util"
)

// Options is a structure used to hold the route configuration options that can be supplied for the backend routes.
type Options struct {
Algorithm string `json:"alg"`
}

// Host is a structure that holds the host info for the backend route.
type Host struct {
Protocol string `json:"protocol"`
Hostname string `json:"hostname"`
Port int `json:"port"`
}

// BackendRoute holds all the information about a configured route, for which Traffic Ops serves as a reverse proxy.
type BackendRoute struct {
Path string `json:"path"`
Method string `json:"method"`
Hosts []Host `json:"hosts"`
Opts Options `json:"opts"`
ID int `json:"routeId"`
Insecure bool `json:"insecure"`
Permissions []string `json:"permissions"`
Index int
}

// BackendConfig is a structure that holds the configuration supplied to Traffic Ops, which makes it act as a reverse proxy to the specified routes.
type BackendConfig struct {
Routes []BackendRoute `json:"routes"`
}

// Config reflects the structure of the cdn.conf file
type Config struct {
URL *url.URL `json:"-"`
Expand Down Expand Up @@ -286,6 +315,31 @@ func (c Config) EventLog() log.LogLocation {
const BlockStartup = true
const AllowStartup = false

func LoadBackendConfig(backendConfigPath string) (BackendConfig, error) {
confBytes, err := ioutil.ReadFile(backendConfigPath)
if err != nil {
return BackendConfig{}, fmt.Errorf("reading backend conf '%s': %v", backendConfigPath, err)
}

cfg := BackendConfig{}
err = json.Unmarshal(confBytes, &cfg)
if err != nil {
return BackendConfig{}, fmt.Errorf("unmarshalling '%s': %v", backendConfigPath, err)
}
for _, r := range cfg.Routes {
if r.Opts.Algorithm != "" && r.Opts.Algorithm != "roundrobin" {
return cfg, errors.New("algorithm can only be roundrobin or blank")
}
for _, h := range r.Hosts {
rawURL := h.Protocol + "://" + h.Hostname + ":" + strconv.Itoa(h.Port)
if _, err = url.ParseRequestURI(rawURL); err != nil {
return cfg, fmt.Errorf("couldn't convert host info into a valid URI: %v", err)
}
}
}
return cfg, nil
}

func LoadCdnConfig(cdnConfPath string) (Config, error) {
// load json from cdn.conf
confBytes, err := ioutil.ReadFile(cdnConfPath)
Expand Down
10 changes: 9 additions & 1 deletion traffic_ops/traffic_ops_golang/routing/middleware/wrappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func WrapAccessLog(secret string, h http.Handler) http.HandlerFunc {
imsType = IMSMISS
}
}
log.EventfRaw(`%s - %s [%s] "%v %v?%v %s" %v %v %v "%v" %v %s`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, r.URL.RawQuery, r.Proto, iw.Code, iw.ByteCount, int(time.Now().Sub(start)/time.Millisecond), r.UserAgent(), r.Header.Get(RouteID), imsType)
log.EventfRaw(`%s - %s [%s] "%v %v?%v %s" %v %v %v "%v" %v %s`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, r.URL.RawQuery, r.Proto, iw.Code, iw.ByteCount, int(time.Now().Sub(start)/time.Millisecond), r.UserAgent(), r.Context().Value(RouteID), imsType)
}()
h.ServeHTTP(iw, r)
}
Expand Down Expand Up @@ -276,6 +276,14 @@ func NotImplementedHandler() http.Handler {
})
}

func BackendErrorHandler(code int, userErr error, sysErr error) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(rfc.ContentType, rfc.ApplicationJSON)
w.WriteHeader(code)
api.HandleErr(w, r, nil, code, userErr, sysErr)
})
}

// DisabledRouteHandler returns a http.Handler which returns a HTTP 5xx code to the client, and an error message indicating the route is currently disabled.
// This is used for routes which have been disabled via configuration. See config.ConfigTrafficOpsGolang.RoutingBlacklist.DisabledRoutes.
func DisabledRouteHandler() http.Handler {
Expand Down
Loading

0 comments on commit 8a5e532

Please sign in to comment.