Skip to content

Commit 137da27

Browse files
authored
feat(service): add ip address in router logs (#5789)
1 parent 00d5b6f commit 137da27

35 files changed

+229
-153
lines changed

engine/api/api.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ type Configuration struct {
6464
API string `toml:"api" default:"http://localhost:8081" json:"api"`
6565
UI string `toml:"ui" default:"http://localhost:8080" json:"ui"`
6666
} `toml:"url" comment:"#####################\n CDS URLs Settings \n####################" json:"url"`
67-
HTTP struct {
68-
Addr string `toml:"addr" default:"" commented:"true" comment:"Listen HTTP address without port, example: 127.0.0.1" json:"addr"`
69-
Port int `toml:"port" default:"8081" json:"port"`
70-
} `toml:"http" json:"http"`
67+
HTTP service.HTTPRouterConfiguration `toml:"http" json:"http"`
7168
Secrets struct {
7269
Key string `toml:"key" json:"-"`
7370
} `toml:"secrets" json:"secrets"`
@@ -552,6 +549,7 @@ func (a *API) Serve(ctx context.Context) error {
552549
a.Router = &Router{
553550
Mux: mux.NewRouter(),
554551
Background: ctx,
552+
Config: a.Config.HTTP,
555553
}
556554
a.InitRouter()
557555
if err := a.initWebsocket(event.DefaultPubSubKey); err != nil {

engine/api/api_routes.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ func (api *API) InitRouter() {
443443
r.Handle("/template/{groupName}/{templateSlug}/usage", Scope(sdk.AuthConsumerScopeTemplate), r.GET(api.getTemplateUsageHandler))
444444

445445
//Not Found handler
446-
r.Mux.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
446+
r.Mux.NotFoundHandler = http.HandlerFunc(r.NotFoundHandler)
447447

448448
r.computeScopeDetails()
449449
}

engine/api/config.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,18 @@ func (api *API) ConfigVCShandler() service.Handler {
3333

3434
func (api *API) ConfigCDNHandler() service.Handler {
3535
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
36-
tcpURL, err := services.GetCDNPublicTCPAdress(ctx, api.mustDB())
36+
tcpURL, tcpURLEnableTLS, err := services.GetCDNPublicTCPAdress(ctx, api.mustDB())
3737
if err != nil {
3838
return err
3939
}
4040
httpURL, err := services.GetCDNPublicHTTPAdress(ctx, api.mustDB())
4141
if err != nil {
4242
return err
4343
}
44-
return service.WriteJSON(w, sdk.CDNConfig{TCPURL: tcpURL, HTTPURL: httpURL}, http.StatusOK)
44+
return service.WriteJSON(w,
45+
sdk.CDNConfig{TCPURL: tcpURL,
46+
TCPURLEnableTLS: tcpURLEnableTLS,
47+
HTTPURL: httpURL},
48+
http.StatusOK)
4549
}
4650
}

engine/api/router.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type Router struct {
5959
nbPanic int
6060
lastPanic *time.Time
6161
scopeDetails []sdk.AuthConsumerScopeDetail
62+
Config service.HTTPRouterConfiguration
6263
}
6364

6465
// HandlerConfigFunc is a type used in the router configuration fonction "Handle"
@@ -224,7 +225,6 @@ func (r *Router) computeScopeDetails() {
224225
Methods: methods,
225226
})
226227
}
227-
228228
details[i].Scope = scope
229229
details[i].Endpoints = endpoints
230230
}
@@ -340,13 +340,21 @@ func (r *Router) handle(uri string, scope HandlerScope, handlers ...*service.Han
340340
telemetry.Path, req.URL.Path,
341341
telemetry.Method, req.Method)
342342

343+
// Retrieve the client ip address from the header (X-Forwarded-For by default)
344+
clientIP := req.Header.Get(r.Config.HeaderXForwardedFor)
345+
if clientIP == "" {
346+
// If the header has not been found, fallback on the remote adress from the http request
347+
clientIP = req.RemoteAddr
348+
}
349+
343350
// Prepare logging fields
344351
ctx = context.WithValue(ctx, cdslog.Method, req.Method)
345352
ctx = context.WithValue(ctx, cdslog.Route, cleanURL)
346353
ctx = context.WithValue(ctx, cdslog.RequestURI, req.RequestURI)
347354
ctx = context.WithValue(ctx, cdslog.Deprecated, rc.IsDeprecated)
348355
ctx = context.WithValue(ctx, cdslog.Handler, rc.Name)
349356
ctx = context.WithValue(ctx, cdslog.Action, rc.Name)
357+
ctx = context.WithValue(ctx, cdslog.IPAddress, clientIP)
350358

351359
var fields = mux.Vars(req)
352360
for k, v := range fields {
@@ -534,8 +542,22 @@ func MaintenanceAware() service.HandlerConfigParam {
534542
}
535543

536544
// NotFoundHandler is called by default by Mux is any matching handler has been found
537-
func NotFoundHandler(w http.ResponseWriter, req *http.Request) {
538-
service.WriteError(context.Background(), w, req, sdk.NewError(sdk.ErrNotFound, fmt.Errorf("%s not found", req.URL.Path)))
545+
func (r *Router) NotFoundHandler(w http.ResponseWriter, req *http.Request) {
546+
ctx := req.Context()
547+
548+
// Retrieve the client ip address from the header (X-Forwarded-For by default)
549+
clientIP := req.Header.Get(r.Config.HeaderXForwardedFor)
550+
if clientIP == "" {
551+
// If the header has not been found, fallback on the remote adress from the http request
552+
clientIP = req.RemoteAddr
553+
}
554+
555+
// Prepare logging fields
556+
ctx = context.WithValue(ctx, cdslog.Method, req.Method)
557+
ctx = context.WithValue(ctx, cdslog.RequestURI, req.RequestURI)
558+
ctx = context.WithValue(ctx, cdslog.IPAddress, clientIP)
559+
560+
service.WriteError(ctx, w, req, sdk.NewError(sdk.ErrNotFound, fmt.Errorf("%s not found", req.URL.Path)))
539561
}
540562

541563
// StatusPanic returns router status. If nbPanic > 30 -> Alert, if nbPanic > 0 -> Warn

engine/api/services/cdn.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,29 @@ import (
88
"github.com/ovh/cds/sdk"
99
)
1010

11-
func GetCDNPublicTCPAdress(ctx context.Context, db gorp.SqlExecutor) (string, error) {
11+
func GetCDNPublicTCPAdress(ctx context.Context, db gorp.SqlExecutor) (string, bool, error) {
1212
srvs, err := LoadAllByType(ctx, db, sdk.TypeCDN)
1313
if err != nil {
14-
return "", err
14+
return "", false, err
1515
}
16+
17+
var tcp_addr string
18+
var tcp_tls bool
19+
20+
findAddr:
1621
for _, svr := range srvs {
1722
if addr, ok := svr.Config["public_tcp"]; ok {
18-
return addr.(string), nil
23+
tcp_addr = addr.(string)
24+
if tls, ok := svr.Config["public_tcp_enable_tls"]; ok {
25+
tcp_tls = tls.(bool)
26+
}
27+
break findAddr
1928
}
2029
}
21-
return "", sdk.NewErrorFrom(sdk.ErrNotFound, "unable to find any tcp configuration in CDN Uservice")
30+
if tcp_addr != "" {
31+
return tcp_addr, tcp_tls, nil
32+
}
33+
return "", false, sdk.NewErrorFrom(sdk.ErrNotFound, "unable to find any tcp configuration in CDN Uservice")
2234
}
2335

2436
func GetCDNPublicHTTPAdress(ctx context.Context, db gorp.SqlExecutor) (string, error) {

engine/api/test/assets/assets.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,9 @@ func InitCDNService(t *testing.T, db gorpmapper.SqlExecutorWithTx, scopes ...sdk
545545
PublicKey: publicKey,
546546
ConsumerID: &hConsumer.ID,
547547
Config: map[string]interface{}{
548-
"public_tcp": "cdn.net:4545",
549-
"public_http": "http://cdn.net:8080",
548+
"public_tcp": "cdn.net:4545",
549+
"public_http": "http://cdn.net:8080",
550+
"public_tcp_enable_tls": true,
550551
},
551552
},
552553
}

engine/api/workflow_queue.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func (api *API) postTakeWorkflowJobHandler() service.Handler {
111111

112112
// Get CDN TCP Addr
113113
// Get CDN TCP Addr
114-
pbji.GelfServiceAddr, err = services.GetCDNPublicTCPAdress(ctx, api.mustDB())
114+
pbji.GelfServiceAddr, pbji.GelfServiceAddrEnableTLS, err = services.GetCDNPublicTCPAdress(ctx, api.mustDB())
115115
if err != nil {
116116
return err
117117
}

engine/api/workflow_queue_test.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ import (
66
"encoding/base64"
77
"encoding/json"
88
"fmt"
9-
"github.com/ovh/cds/engine/api/bootstrap"
10-
"github.com/ovh/cds/engine/api/database/gorpmapping"
11-
"github.com/ovh/cds/engine/featureflipping"
129
"io/ioutil"
1310
"net/http"
1411
"net/http/httptest"
@@ -18,6 +15,10 @@ import (
1815
"testing"
1916
"time"
2017

18+
"github.com/ovh/cds/engine/api/bootstrap"
19+
"github.com/ovh/cds/engine/api/database/gorpmapping"
20+
"github.com/ovh/cds/engine/featureflipping"
21+
2122
"github.com/ovh/venom"
2223

2324
"github.com/rockbears/log"
@@ -484,6 +485,7 @@ func Test_postTakeWorkflowJobHandler(t *testing.T) {
484485
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), pbji))
485486

486487
assert.Equal(t, "cdn.net:4545", pbji.GelfServiceAddr)
488+
assert.Equal(t, true, pbji.GelfServiceAddrEnableTLS)
487489

488490
run, err := workflow.LoadNodeJobRun(context.TODO(), api.mustDB(), api.Cache, ctx.job.ID)
489491
require.NoError(t, err)

engine/cdn/cdn.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ const (
3737
func New() *Service {
3838
s := new(Service)
3939
s.GoRoutines = sdk.NewGoRoutines()
40-
s.Router = &api.Router{
41-
Mux: mux.NewRouter(),
42-
}
4340

4441
return s
4542
}
@@ -50,7 +47,10 @@ func (s *Service) Init(config interface{}) (cdsclient.ServiceConfig, error) {
5047
if !ok {
5148
return cfg, sdk.WithStack(fmt.Errorf("invalid CDN service configuration"))
5249
}
53-
50+
s.Router = &api.Router{
51+
Mux: mux.NewRouter(),
52+
Config: sConfig.HTTP,
53+
}
5454
cfg.Host = sConfig.API.HTTP.URL
5555
cfg.Token = sConfig.API.Token
5656
cfg.InsecureSkipVerifyTLS = sConfig.API.HTTP.Insecure

engine/cdn/types.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,15 @@ type Service struct {
6464

6565
// Configuration is the hooks configuration structure
6666
type Configuration struct {
67-
Name string `toml:"name" default:"cds-cdn" comment:"Name of this CDS CDN Service\n Enter a name to enable this service" json:"name"`
68-
TCP sdk.TCPServer `toml:"tcp" comment:"######################\n CDS CDN TCP Configuration \n######################" json:"tcp"`
69-
HTTP struct {
70-
Addr string `toml:"addr" default:"" commented:"true" comment:"Listen address without port, example: 127.0.0.1" json:"addr"`
71-
Port int `toml:"port" default:"8089" json:"port"`
72-
} `toml:"http" comment:"######################\n CDS CDN HTTP Configuration \n######################" json:"http"`
73-
URL string `default:"http://localhost:8089" json:"url" comment:"Private URL for communication with API"`
74-
PublicTCP string `toml:"publicTCP" default:"localhost:8090" comment:"Public address to access to CDN TCP server" json:"public_tcp"`
75-
PublicHTTP string `toml:"publicHTTP" default:"http://localhost:8089" comment:"Public address to access to CDN HTTP server" json:"public_http"`
76-
Database database.DBConfigurationWithEncryption `toml:"database" comment:"################################\n Postgresql Database settings \n###############################" json:"database"`
77-
Cache struct {
67+
Name string `toml:"name" default:"cds-cdn" comment:"Name of this CDS CDN Service\n Enter a name to enable this service" json:"name"`
68+
TCP sdk.TCPServer `toml:"tcp" comment:"######################\n CDS CDN TCP Configuration \n######################" json:"tcp"`
69+
HTTP service.HTTPRouterConfiguration `toml:"http" comment:"######################\n CDS CDN HTTP Configuration \n######################" json:"http"`
70+
URL string `default:"http://localhost:8089" json:"url" comment:"Private URL for communication with API"`
71+
PublicTCP string `toml:"publicTCP" default:"localhost:8090" comment:"Public address to access to CDN TCP server" json:"public_tcp"`
72+
PublicTCPEnableTLS bool `toml:"publicTCPEnableTLS" comment:"Enable TLS on public address to access to CDN TCP server" json:"public_tcp_enable_tls"`
73+
PublicHTTP string `toml:"publicHTTP" default:"http://localhost:8089" comment:"Public address to access to CDN HTTP server" json:"public_http"`
74+
Database database.DBConfigurationWithEncryption `toml:"database" comment:"################################\n Postgresql Database settings \n###############################" json:"database"`
75+
Cache struct {
7876
TTL int `toml:"ttl" default:"60" json:"ttl"`
7977
LruSize int64 `toml:"lruSize" default:"134217728" json:"lruSize" comment:"Redis LRU cache for logs items in bytes (default: 128MB)"`
8078
Redis struct {

engine/config.go

+14
Original file line numberDiff line numberDiff line change
@@ -80,32 +80,39 @@ func configBootstrap(args []string) Configuration {
8080
HealthURL: "https://ovh.github.io",
8181
Type: "doc",
8282
})
83+
conf.API.HTTP.Port = 8081
8384
case sdk.TypeUI:
8485
conf.UI = &ui.Configuration{}
8586
conf.UI.Name = "cds-ui-" + namesgenerator.GetRandomNameCDS(0)
8687
defaults.SetDefaults(conf.UI)
88+
conf.UI.HTTP.Port = 8080
8789
case "migrate":
8890
conf.DatabaseMigrate = &migrateservice.Configuration{}
8991
defaults.SetDefaults(conf.DatabaseMigrate)
9092
conf.DatabaseMigrate.Name = "cds-migrate-" + namesgenerator.GetRandomNameCDS(0)
9193
conf.DatabaseMigrate.ServiceAPI.DB.Schema = "public"
9294
conf.DatabaseMigrate.ServiceCDN.DB.Schema = "cdn"
95+
conf.DatabaseMigrate.HTTP.Port = 8087
9396
case sdk.TypeHatchery + ":local":
9497
conf.Hatchery.Local = &local.HatcheryConfiguration{}
9598
defaults.SetDefaults(conf.Hatchery.Local)
9699
conf.Hatchery.Local.Name = "cds-hatchery-local-" + namesgenerator.GetRandomNameCDS(0)
100+
conf.Hatchery.Local.HTTP.Port = 8086
97101
case sdk.TypeHatchery + ":kubernetes":
98102
conf.Hatchery.Kubernetes = &kubernetes.HatcheryConfiguration{}
99103
defaults.SetDefaults(conf.Hatchery.Kubernetes)
100104
conf.Hatchery.Kubernetes.Name = "cds-hatchery-kubernetes-" + namesgenerator.GetRandomNameCDS(0)
105+
conf.Hatchery.Kubernetes.HTTP.Port = 8086
101106
case sdk.TypeHatchery + ":marathon":
102107
conf.Hatchery.Marathon = &marathon.HatcheryConfiguration{}
103108
defaults.SetDefaults(conf.Hatchery.Marathon)
104109
conf.Hatchery.Marathon.Name = "cds-hatchery-marathon-" + namesgenerator.GetRandomNameCDS(0)
110+
conf.Hatchery.Marathon.HTTP.Port = 8086
105111
case sdk.TypeHatchery + ":openstack":
106112
conf.Hatchery.Openstack = &openstack.HatcheryConfiguration{}
107113
defaults.SetDefaults(conf.Hatchery.Openstack)
108114
conf.Hatchery.Openstack.Name = "cds-hatchery-openstack-" + namesgenerator.GetRandomNameCDS(0)
115+
conf.Hatchery.Openstack.HTTP.Port = 8086
109116
case sdk.TypeHatchery + ":swarm":
110117
conf.Hatchery.Swarm = &swarm.HatcheryConfiguration{}
111118
defaults.SetDefaults(conf.Hatchery.Swarm)
@@ -115,14 +122,17 @@ func configBootstrap(args []string) Configuration {
115122
},
116123
}
117124
conf.Hatchery.Swarm.Name = "cds-hatchery-swarm-" + namesgenerator.GetRandomNameCDS(0)
125+
conf.Hatchery.Swarm.HTTP.Port = 8086
118126
case sdk.TypeHatchery + ":vsphere":
119127
conf.Hatchery.VSphere = &vsphere.HatcheryConfiguration{}
120128
defaults.SetDefaults(conf.Hatchery.VSphere)
121129
conf.Hatchery.VSphere.Name = "cds-hatchery-vsphere-" + namesgenerator.GetRandomNameCDS(0)
130+
conf.Hatchery.VSphere.HTTP.Port = 8086
122131
case sdk.TypeHooks:
123132
conf.Hooks = &hooks.Configuration{}
124133
defaults.SetDefaults(conf.Hooks)
125134
conf.Hooks.Name = "cds-hooks-" + namesgenerator.GetRandomNameCDS(0)
135+
conf.Hooks.HTTP.Port = 8083
126136
case sdk.TypeVCS:
127137
conf.VCS = &vcs.Configuration{}
128138
defaults.SetDefaults(conf.VCS)
@@ -144,13 +154,16 @@ func configBootstrap(args []string) Configuration {
144154
"gerrit": {URL: "http://localhost:8080", Gerrit: &gerrit},
145155
}
146156
conf.VCS.Name = "cds-vcs-" + namesgenerator.GetRandomNameCDS(0)
157+
conf.VCS.HTTP.Port = 8084
147158
case sdk.TypeRepositories:
148159
conf.Repositories = &repositories.Configuration{}
149160
defaults.SetDefaults(conf.Repositories)
150161
conf.Repositories.Name = "cds-repositories-" + namesgenerator.GetRandomNameCDS(0)
162+
conf.Repositories.HTTP.Port = 8085
151163
case sdk.TypeCDN:
152164
conf.CDN = &cdn.Configuration{}
153165
defaults.SetDefaults(conf.CDN)
166+
conf.CDN.HTTP.Port = 8089
154167
conf.CDN.Database.Schema = "cdn"
155168
conf.CDN.Units.HashLocatorSalt = sdk.RandomString(8)
156169
conf.CDN.Units.Buffers = map[string]storage.BufferConfiguration{
@@ -193,6 +206,7 @@ func configBootstrap(args []string) Configuration {
193206
case sdk.TypeElasticsearch:
194207
conf.ElasticSearch = &elasticsearch.Configuration{}
195208
defaults.SetDefaults(conf.ElasticSearch)
209+
conf.ElasticSearch.HTTP.Port = 8088
196210
default:
197211
sdk.Exit("Error service '%s' is unknown", a)
198212
}

engine/elasticsearch/elasticsearch.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ var esClient *elastic.Client
2121
func New() *Service {
2222
s := new(Service)
2323
s.GoRoutines = sdk.NewGoRoutines()
24-
s.Router = &api.Router{
25-
Mux: mux.NewRouter(),
26-
}
2724
return s
2825
}
2926

@@ -37,7 +34,10 @@ func (s *Service) ApplyConfiguration(config interface{}) error {
3734
if !ok {
3835
return fmt.Errorf("ApplyConfiguration> Invalid Elasticsearch configuration")
3936
}
40-
37+
s.Router = &api.Router{
38+
Mux: mux.NewRouter(),
39+
Config: s.Cfg.HTTP,
40+
}
4141
s.HTTPURL = s.Cfg.URL
4242
s.ServiceName = s.Cfg.Name
4343
s.ServiceType = sdk.TypeElasticsearch

engine/elasticsearch/types.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ type Service struct {
1616

1717
// Configuration is the vcs configuration structure
1818
type Configuration struct {
19-
Name string `toml:"name" comment:"Name of this CDS elasticsearch Service\n Enter a name to enable this service" json:"name"`
20-
HTTP struct {
21-
Addr string `toml:"addr" default:"" commented:"true" comment:"Listen address without port, example: 127.0.0.1" json:"addr"`
22-
Port int `toml:"port" default:"8088" json:"port"`
23-
} `toml:"http" comment:"######################\n CDS Elasticsearch HTTP Configuration \n######################" json:"http"`
24-
URL string `default:"http://localhost:8088" json:"url"`
19+
Name string `toml:"name" comment:"Name of this CDS elasticsearch Service\n Enter a name to enable this service" json:"name"`
20+
HTTP service.HTTPRouterConfiguration `toml:"http" comment:"######################\n CDS Elasticsearch HTTP Configuration \n######################" json:"http"`
21+
URL string `default:"http://localhost:8088" json:"url"`
2522
ElasticSearch struct {
2623
URL string `toml:"url" json:"url"`
2724
Username string `toml:"username" json:"username"`

engine/hatchery/kubernetes/kubernetes.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ import (
3030
func New() *HatcheryKubernetes {
3131
s := new(HatcheryKubernetes)
3232
s.GoRoutines = sdk.NewGoRoutines()
33-
s.Router = &api.Router{
34-
Mux: mux.NewRouter(),
35-
}
3633
return s
3734
}
3835

@@ -57,6 +54,11 @@ func (h *HatcheryKubernetes) Init(config interface{}) (cdsclient.ServiceConfig,
5754
return cfg, sdk.WithStack(fmt.Errorf("invalid kubernetes hatchery configuration"))
5855
}
5956

57+
h.Router = &api.Router{
58+
Mux: mux.NewRouter(),
59+
Config: sConfig.HTTP,
60+
}
61+
6062
cfg.Host = sConfig.API.HTTP.URL
6163
cfg.Token = sConfig.API.Token
6264
cfg.InsecureSkipVerifyTLS = sConfig.API.HTTP.Insecure

0 commit comments

Comments
 (0)