You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ra...@apache.org on 2022/05/10 14:57:52 UTC
[trafficcontrol] branch master updated: Convert Traffic Ops into a Service Oriented architecture(SOA) product (#6754)
This is an automated email from the ASF dual-hosted git repository.
rawlin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new 000c1b9133 Convert Traffic Ops into a Service Oriented architecture(SOA) product (#6754)
000c1b9133 is described below
commit 000c1b913317f3936f8ed3491030ed17052fcbba
Author: Srijeet Chatterjee <30...@users.noreply.github.com>
AuthorDate: Tue May 10 08:57:46 2022 -0600
Convert Traffic Ops into a Service Oriented architecture(SOA) product (#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
---
CHANGELOG.md | 1 +
docs/source/admin/traffic_ops.rst | 34 +++++-
traffic_ops/app/conf/backends.conf | 52 +++++++++
traffic_ops/app/conf/production/backends.conf | 3 +
traffic_ops/etc/init.d/traffic_ops | 2 +-
traffic_ops/traffic_ops_golang/config/config.go | 54 +++++++++
.../routing/middleware/wrappers.go | 10 +-
traffic_ops/traffic_ops_golang/routing/routing.go | 123 ++++++++++++++++++++-
.../traffic_ops_golang/traffic_ops_golang.go | 40 ++++++-
9 files changed, 308 insertions(+), 11 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a6c302f728..7c6565a933 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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}.
diff --git a/docs/source/admin/traffic_ops.rst b/docs/source/admin/traffic_ops.rst
index d0b1d84120..6ea3cbf479 100644
--- a/docs/source/admin/traffic_ops.rst
+++ b/docs/source/admin/traffic_ops.rst
@@ -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:
@@ -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
@@ -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.
@@ -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.
diff --git a/traffic_ops/app/conf/backends.conf b/traffic_ops/app/conf/backends.conf
new file mode 100644
index 0000000000..2401a44996
--- /dev/null
+++ b/traffic_ops/app/conf/backends.conf
@@ -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"
+ }
+ }
+ ]
+}
diff --git a/traffic_ops/app/conf/production/backends.conf b/traffic_ops/app/conf/production/backends.conf
new file mode 100644
index 0000000000..4feaf1db51
--- /dev/null
+++ b/traffic_ops/app/conf/production/backends.conf
@@ -0,0 +1,3 @@
+{
+ "routes": [],
+}
diff --git a/traffic_ops/etc/init.d/traffic_ops b/traffic_ops/etc/init.d/traffic_ops
index d2fad881b1..12674c981b 100755
--- a/traffic_ops/etc/init.d/traffic_ops
+++ b/traffic_ops/etc/init.d/traffic_ops
@@ -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 ()
diff --git a/traffic_ops/traffic_ops_golang/config/config.go b/traffic_ops/traffic_ops_golang/config/config.go
index f9680c10a3..521da1d9bd 100644
--- a/traffic_ops/traffic_ops_golang/config/config.go
+++ b/traffic_ops/traffic_ops_golang/config/config.go
@@ -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:"-"`
@@ -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)
diff --git a/traffic_ops/traffic_ops_golang/routing/middleware/wrappers.go b/traffic_ops/traffic_ops_golang/routing/middleware/wrappers.go
index e307faadb9..57ed0bb520 100644
--- a/traffic_ops/traffic_ops_golang/routing/middleware/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/routing/middleware/wrappers.go
@@ -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)
}
@@ -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 {
diff --git a/traffic_ops/traffic_ops_golang/routing/routing.go b/traffic_ops/traffic_ops_golang/routing/routing.go
index 3031e1c209..c3ca1adcb4 100644
--- a/traffic_ops/traffic_ops_golang/routing/routing.go
+++ b/traffic_ops/traffic_ops_golang/routing/routing.go
@@ -23,18 +23,23 @@ package routing
import (
"context"
+ "crypto/tls"
"errors"
"fmt"
"net/http"
+ "net/http/httputil"
+ "net/url"
"regexp"
"sort"
"strconv"
"strings"
+ "sync"
"sync/atomic"
"time"
"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+ "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/plugin"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/routing/middleware"
@@ -46,6 +51,28 @@ import (
// RoutePrefix is a prefix that all API routes must match.
const RoutePrefix = "^api" // TODO config?
+type backendConfigSynced struct {
+ cfg config.BackendConfig
+ *sync.RWMutex
+}
+
+// backendCfg stores the current backend config supplied to traffic ops.
+var backendCfg = backendConfigSynced{RWMutex: &sync.RWMutex{}}
+
+// GetBackendConfig returns the current BackendConfig.
+func GetBackendConfig() config.BackendConfig {
+ backendCfg.RLock()
+ defer backendCfg.RUnlock()
+ return backendCfg.cfg
+}
+
+// SetBackendConfig sets the BackendConfig to the value supplied.
+func SetBackendConfig(backendConfig config.BackendConfig) {
+ backendCfg.Lock()
+ defer backendCfg.Unlock()
+ backendCfg.cfg = backendConfig
+}
+
// A Route defines an association with a client request and a handler for that
// request.
type Route struct {
@@ -85,6 +112,7 @@ type ServerData struct {
Profiling *bool // Yes this is a field in the config but we want to live reload this value and NOT the entire config
Plugins plugin.Plugins
TrafficVault trafficvault.TrafficVault
+ Mux *http.ServeMux
}
// CompiledRoute ...
@@ -270,8 +298,8 @@ func Handler(
}
routeCtx := context.WithValue(ctx, api.PathParamsKey, params)
+ routeCtx = context.WithValue(routeCtx, middleware.RouteID, strconv.Itoa(compiledRoute.ID))
r = r.WithContext(routeCtx)
- r.Header.Add(middleware.RouteID, strconv.Itoa(compiledRoute.ID))
compiledRoute.Handler(w, r)
return
}
@@ -280,8 +308,97 @@ func Handler(
h.ServeHTTP(w, r)
return
}
+ var backendRouteHandled bool
+ backendConfig := GetBackendConfig()
+ for i, backendRoute := range backendConfig.Routes {
+ var params []string
+ routeParams := map[string]string{}
+ if backendRoute.Method == r.Method {
+ for open := strings.Index(backendRoute.Path, "{"); open > 0; open = strings.Index(backendRoute.Path, "{") {
+ close := strings.Index(backendRoute.Path, "}")
+ if close < 0 {
+ panic("malformed route")
+ }
+ param := backendRoute.Path[open+1 : close]
+ params = append(params, param)
+ backendRoute.Path = backendRoute.Path[:open] + `([^/]+)` + backendRoute.Path[close+1:]
+ }
+ regex := regexp.MustCompile(backendRoute.Path)
+ match := regex.FindStringSubmatch(r.URL.Path)
+ if len(match) == 0 {
+ continue
+ }
+ for i, v := range params {
+ routeParams[v] = match[i+1]
+ }
+ if backendRoute.Opts.Algorithm == "" || backendRoute.Opts.Algorithm == "roundrobin" {
+ index := backendRoute.Index % len(backendRoute.Hosts)
+ host := backendRoute.Hosts[index]
+ backendRoute.Index++
+ backendConfig.Routes[i] = backendRoute
+ backendRouteHandled = true
+ rp := httputil.NewSingleHostReverseProxy(&url.URL{
+ Host: host.Hostname + ":" + strconv.Itoa(host.Port),
+ Scheme: host.Protocol,
+ })
+ rp.Transport = &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: backendRoute.Insecure},
+ }
+ rp.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
+ api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, err)
+ return
+ }
+ routeCtx := context.WithValue(ctx, api.DBContextKey, db)
+ routeCtx = context.WithValue(routeCtx, api.PathParamsKey, routeParams)
+ routeCtx = context.WithValue(routeCtx, middleware.RouteID, strconv.Itoa(backendRoute.ID))
+ r = r.WithContext(routeCtx)
+ userErr, sysErr, code := HandleBackendRoute(cfg, backendRoute, w, r)
+ if userErr != nil || sysErr != nil {
+ h2 := middleware.WrapAccessLog(cfg.Secrets[0], middleware.BackendErrorHandler(code, userErr, sysErr))
+ h2.ServeHTTP(w, r)
+ return
+ }
+ backendHandler := middleware.WrapAccessLog(cfg.Secrets[0], rp)
+ backendHandler.ServeHTTP(w, r)
+ return
+ } else {
+ h2 := middleware.WrapAccessLog(cfg.Secrets[0], middleware.BackendErrorHandler(http.StatusBadRequest, errors.New("only an algorithm of roundrobin is supported by the backend options currently"), nil))
+ h2.ServeHTTP(w, r)
+ return
+ }
+ }
+ }
+ if !backendRouteHandled {
+ catchall.ServeHTTP(w, r)
+ }
+}
- catchall.ServeHTTP(w, r)
+// HandleBackendRoute does all the pre processing for the backend routes.
+func HandleBackendRoute(cfg *config.Config, route config.BackendRoute, w http.ResponseWriter, r *http.Request) (error, error, int) {
+ var userErr, sysErr error
+ var errCode int
+ var user auth.CurrentUser
+ var inf *api.APIInfo
+
+ user, userErr, sysErr, errCode = api.GetUserFromReq(w, r, cfg.Secrets[0])
+ if userErr != nil || sysErr != nil {
+ return userErr, sysErr, errCode
+ }
+ if cfg.RoleBasedPermissions {
+ missingPerms := user.MissingPermissions(route.Permissions...)
+ if len(missingPerms) != 0 {
+ msg := strings.Join(missingPerms, ", ")
+ return fmt.Errorf("missing required Permissions: %s", msg), nil, http.StatusForbidden
+ }
+ }
+ api.AddUserToReq(r, user)
+ var params []string
+ inf, userErr, sysErr, errCode = api.NewInfo(r, params, nil)
+ if userErr != nil || sysErr != nil {
+ return userErr, sysErr, errCode
+ }
+ defer inf.Close()
+ return nil, nil, http.StatusOK
}
// IsRequestAPIAndUnknownVersion returns true if the request starts with `/api` and is a version not in the list of versions.
@@ -335,7 +452,7 @@ func RegisterRoutes(d ServerData) error {
compiledRoutes := CompileRoutes(routes)
getReqID := nextReqIDGetter()
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ d.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
Handler(compiledRoutes, versions, catchall, d.DB, &d.Config, getReqID, d.Plugins, d.TrafficVault, w, r)
})
return nil
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index a04c486d36..42a3acf45e 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -22,6 +22,7 @@ package main
import (
"crypto/tls"
"encoding/json"
+ "errors"
"flag"
"fmt"
"io/ioutil"
@@ -64,6 +65,7 @@ func main() {
configFileName := flag.String("cfg", "", "The config file path")
dbConfigFileName := flag.String("dbcfg", "", "The db config file path")
riakConfigFileName := flag.String("riakcfg", "", "The riak config file path (DEPRECATED: use traffic_vault_backend = riak and traffic_vault_config in cdn.conf instead)")
+ backendConfigFileName := flag.String("backendcfg", "", "The backend config file path")
flag.Parse()
if *showVersion {
@@ -164,7 +166,18 @@ func main() {
log.Errorln(debugServer.ListenAndServe())
}()
- if err := routing.RegisterRoutes(routing.ServerData{DB: db, Config: cfg, Profiling: &profiling, Plugins: plugins, TrafficVault: trafficVault}); err != nil {
+ var backendConfig config.BackendConfig
+ if *backendConfigFileName != "" {
+ backendConfig, err = config.LoadBackendConfig(*backendConfigFileName)
+ routing.SetBackendConfig(backendConfig)
+ if err != nil {
+ log.Errorf("error loading backend config: %v", err)
+ }
+ }
+
+ mux := http.NewServeMux()
+ d := routing.ServerData{DB: db, Config: cfg, Profiling: &profiling, Plugins: plugins, TrafficVault: trafficVault, Mux: mux}
+ if err := routing.RegisterRoutes(d); err != nil {
log.Errorf("registering routes: %v\n", err)
os.Exit(1)
}
@@ -213,7 +226,7 @@ func main() {
} else {
file.Close()
}
-
+ server.Handler = mux
if err := server.ListenAndServeTLS(cfg.CertPath, cfg.KeyPath); err != nil {
log.Errorf("stopping server: %v\n", err)
os.Exit(1)
@@ -232,10 +245,16 @@ func main() {
continuousProfile(&profiling, &profilingLocation, cfg.Version)
}
- reloadProfilingConfig := func() {
+ reloadProfilingAndBackendConfig := func() {
setNewProfilingInfo(*configFileName, &profiling, &profilingLocation, cfg.Version)
+ backendConfig, err = getNewBackendConfig(backendConfigFileName)
+ if err != nil {
+ log.Errorf("could not reload backend config: %v", err)
+ } else {
+ routing.SetBackendConfig(backendConfig)
+ }
}
- signalReloader(unix.SIGHUP, reloadProfilingConfig)
+ signalReloader(unix.SIGHUP, reloadProfilingAndBackendConfig)
}
func setupTrafficVault(riakConfigFileName string, cfg *config.Config) trafficvault.TrafficVault {
@@ -293,6 +312,19 @@ func setupTrafficVault(riakConfigFileName string, cfg *config.Config) trafficvau
return &disabled.Disabled{}
}
+func getNewBackendConfig(backendConfigFileName *string) (config.BackendConfig, error) {
+ if backendConfigFileName == nil {
+ return config.BackendConfig{}, errors.New("no backend config filename")
+ }
+ log.Infof("setting new backend config to %s", *backendConfigFileName)
+ backendConfig, err := config.LoadBackendConfig(*backendConfigFileName)
+ if err != nil {
+ log.Errorf("error reloading config: %v", err)
+ return backendConfig, err
+ }
+ return backendConfig, nil
+}
+
func setNewProfilingInfo(configFileName string, currentProfilingEnabled *bool, currentProfilingLocation *string, version string) {
newProfilingEnabled, newProfilingLocation, err := reloadProfilingInfo(configFileName)
if err != nil {