Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Traffic Ops into a Service Oriented architecture(SOA) product #6754

Merged
merged 19 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
{
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
"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
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
}

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