Skip to content

Commit 4674140

Browse files
authored
ENH: Adds filtering service processing (#36)
1 parent e977d5b commit 4674140

9 files changed

Lines changed: 80 additions & 1 deletion

File tree

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ENV CERTS="" \
2222
DEFAULT_REQ_MODE="http" \
2323
DO_NOT_RESOLVE_ADDR="false" \
2424
ENABLE_H2="true" \
25+
FILTER_PROXY_INSTANCE_NAME="false" \
2526
HEALTHCHECK="true" \
2627
HTTPS_ONLY="false" \
2728
EXTRA_FRONTEND="" \

Dockerfile.linux-arm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ ENV CERTS="" \
1313
DEFAULT_REQ_MODE="http" \
1414
DO_NOT_RESOLVE_ADDR="false" \
1515
ENABLE_H2="true" \
16+
FILTER_PROXY_INSTANCE_NAME="false" \
1617
HEALTHCHECK="true" \
1718
HTTPS_ONLY="false" \
1819
EXTRA_FRONTEND="" \

actions/reconfigure.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ var NewReconfigure = func(baseData BaseReconfigure, serviceData proxy.Service) R
4747

4848
// Execute creates a new configuration and reloads the proxy
4949
func (m *Reconfigure) Execute(reloadAfter bool) error {
50+
if strings.EqualFold(os.Getenv("FILTER_PROXY_INSTANCE_NAME"), "true") &&
51+
!strings.EqualFold(m.InstanceName, m.Service.ProxyInstanceName) {
52+
return nil
53+
}
5054
mu.Lock()
5155
defer mu.Unlock()
5256
if strings.EqualFold(os.Getenv("SKIP_ADDRESS_VALIDATION"), "false") {

actions/reconfigure_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,70 @@ func (s *ReconfigureTestSuite) Test_Execute_ReturnsError_WhenAddressIsNotAccessi
11241124
s.Error(err)
11251125
}
11261126

1127+
func (s *ReconfigureTestSuite) Test_Execute_WhenFilterProxyInstanceIsTrue_SameProxyInstanceName() {
1128+
mockObj := getProxyMock("")
1129+
proxyOrig := proxy.Instance
1130+
os.Setenv("FILTER_PROXY_INSTANCE_NAME", "true")
1131+
defer func() {
1132+
proxy.Instance = proxyOrig
1133+
os.Unsetenv("FILTER_PROXY_INSTANCE_NAME")
1134+
}()
1135+
proxy.Instance = mockObj
1136+
sd := proxy.ServiceDest{
1137+
ServicePath: []string{"path/to/my/service/api", "path/to/my/other/service/api"},
1138+
}
1139+
expected := proxy.Service{
1140+
ServiceName: s.ServiceName,
1141+
ServiceDest: []proxy.ServiceDest{sd},
1142+
PathType: s.PathType,
1143+
ProxyInstanceName: s.InstanceName,
1144+
}
1145+
r := NewReconfigure(
1146+
BaseReconfigure{
1147+
TemplatesPath: s.TemplatesPath,
1148+
ConfigsPath: s.ConfigsPath,
1149+
InstanceName: s.InstanceName,
1150+
},
1151+
expected,
1152+
)
1153+
1154+
r.Execute(true)
1155+
1156+
mockObj.AssertCalled(s.T(), "AddService", mock.Anything)
1157+
}
1158+
1159+
func (s *ReconfigureTestSuite) Test_Execute_WhenFilterProxyInstanceIsTrue_DifferentProxyInstanceName() {
1160+
mockObj := getProxyMock("")
1161+
proxyOrig := proxy.Instance
1162+
os.Setenv("FILTER_PROXY_INSTANCE_NAME", "true")
1163+
defer func() {
1164+
proxy.Instance = proxyOrig
1165+
os.Unsetenv("FILTER_PROXY_INSTANCE_NAME")
1166+
}()
1167+
proxy.Instance = mockObj
1168+
sd := proxy.ServiceDest{
1169+
ServicePath: []string{"path/to/my/service/api", "path/to/my/other/service/api"},
1170+
}
1171+
expected := proxy.Service{
1172+
ServiceName: s.ServiceName,
1173+
ServiceDest: []proxy.ServiceDest{sd},
1174+
PathType: s.PathType,
1175+
ProxyInstanceName: "another-docker-flow",
1176+
}
1177+
r := NewReconfigure(
1178+
BaseReconfigure{
1179+
TemplatesPath: s.TemplatesPath,
1180+
ConfigsPath: s.ConfigsPath,
1181+
InstanceName: "docker-flow",
1182+
},
1183+
expected,
1184+
)
1185+
1186+
r.Execute(true)
1187+
1188+
mockObj.AssertNotCalled(s.T(), "AddService", mock.Anything)
1189+
}
1190+
11271191
// Mock
11281192

11291193
type ReconfigureMock struct {

docs/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ The following environment variables can be used to configure the *Docker Flow Pr
3030
|ENABLE_H2 |Whether to enable http/2<br>**Example:** `false`<br>**Default:** `true`|
3131
|EXTRA_FRONTEND |Value will be added to the default `frontend` configuration. Multiple lines should be separated with comma (*,*).|
3232
|EXTRA_GLOBAL |Value will be added to the default `global` configuration. Multiple lines should be separated with comma (*,*).|
33+
|FILTER_PROXY_INSTANCE_NAME|If set to `true`, only services with `com.df.proxyInstanceName` equal to env variable `PROXY_INSTANCE_NAME` will be processed by the proxy.<br>**Default:** `false`|
3334
|HTTPS_ONLY |If set to true, all requests to all services will be redirected to HTTPS.<br>**Example:** `true`<br>**Default Value:** `false`|
3435
|LISTENER_ADDRESS |The address of the [Docker Flow: Swarm Listener](https://github.com/docker-flow/docker-flow-swarm-listener) used for automatic proxy configuration. Multiple values can be separated with comma (`,`). When set to multiple values, the proxy will query each address in order.<br>**Example:** `swarm-listener`|
3536
PROXY_INSTANCE_NAME|The name of the proxy instance. Useful if multiple proxies are running inside a cluster.<br>**Default value:** `docker-flow`|

docs/usage.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ The following query parameters can be used only when `reqMode` is set to `http`
5959
|outboundHostname|The hostname where the service is running, for instance on a separate swarm. If specified, the proxy will dispatch requests to that domain. The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `outboundHostname.1`, `outboundHostname.2`, and so on).<br>**Example:** `ecme.com`|
6060
|pathType |The ACL derivative. Defaults to *path_beg*. See [HAProxy path](https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#7.3.6-path) for more info.<br>**Example:** `path_beg`|
6161
|redirectFromDomain|If a request is sent to one of the domains in this list, it will be redirected to one of the values of the `serviceDomain`. Multiple domains can be separated with comma (e.g. `acme.com,something.acme.com`). The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service.<br>**Example:** `acme.com,something.acme.com`|
62+
|proxyInstanceName|When `FILTER_PROXY_INSTANCE_NAME` is set to `true`, only services with proxyInstanceName equal to `PROXY_INSTANCE_NAME` will be configured by this proxy.<br>**Example:** `docker-flow`|
6263
|redirectWhenHttpProto|Whether to redirect to https when X-Forwarded-Proto is set and the request is made over an HTTP port.<br>**Example:** `true`<br>**Default Value:** `false`|
6364
|serviceCert |Content of the PEM-encoded certificate to be used by the proxy when serving traffic over SSL.|
6465
|serviceDomain |The domain of the service. If set, the proxy will allow access only to requests coming to that domain. Multiple domains can be separated with comma (e.g. `acme.com,something.else.com`). The parameter can be prefixed with an index thus allowing definition of multiple destinations for a single service (e.g. `serviceDomain.1`, `serviceDomain.2`, and so on). Asterisk sign can be placed to beginning of value and in this case **serviceDomainAlgo** parameter will be **replaced** to `hdr_end(host)`. This parameter is **mandatory** if `servicePath` is not specified.<br>**Example:** `ecme.com`|

proxy/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ type Service struct {
161161
// The ACL derivative. Defaults to path_beg.
162162
// See https://cbonte.github.io/haproxy-dconv/configuration-1.5.html#7.3.6-path for more info.
163163
PathType string `split_words:"true"`
164+
// When `FILTER_PROXY_INSTANCE_NAME` is set to `true`, only services with
165+
// ProxyInstanceName equal to `PROXY_INSTANCE_NAME` will be configured by this proxy.
166+
ProxyInstanceName string `split_words:"true"`
164167
// Whether to redirect to https when X-Forwarded-Proto is http
165168
RedirectWhenHttpProto bool `split_words:"true"`
166169
// The number of replicas of a service.

proxy/types_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ func (s *TypesTestSuite) getServiceMap(expected Service, indexSuffix, separator
374374
"distribute": strconv.FormatBool(expected.Distribute),
375375
"isDefaultBackend": strconv.FormatBool(expected.IsDefaultBackend),
376376
"pathType": expected.PathType,
377+
"proxyInstanceName": expected.ProxyInstanceName,
377378
"redirectWhenHttpProto": strconv.FormatBool(expected.RedirectWhenHttpProto),
378379
"reqPathReplace": expected.ReqPathReplace,
379380
"reqPathSearch": expected.ReqPathSearch,
@@ -429,6 +430,7 @@ func (s *TypesTestSuite) getExpectedService() Service {
429430
Distribute: true,
430431
IsDefaultBackend: true,
431432
PathType: "pathType",
433+
ProxyInstanceName: "docker-flow",
432434
RedirectWhenHttpProto: true,
433435
ReqPathReplace: "reqPathReplace",
434436
ReqPathSearch: "reqPathSearch",

server/server_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ func (s *ServerTestSuite) Test_GetServiceFromUrl_ReturnsProxyService() {
588588
DiscoveryType: "DNS",
589589
Distribute: true,
590590
PathType: "pathType",
591+
ProxyInstanceName: "docker-flow",
591592
RedirectWhenHttpProto: true,
592593
Replicas: 83,
593594
ReqPathReplace: "reqPathReplace",
@@ -628,7 +629,7 @@ func (s *ServerTestSuite) Test_GetServiceFromUrl_ReturnsProxyService() {
628629
{Username: "user2", Password: "pass2", PassEncrypted: true}},
629630
}
630631
addr := fmt.Sprintf(
631-
"%s?serviceName=%s&users=%s&usersPassEncrypted=%t&aclName=%s&balanceGroup=%s&checkTcp=%t&clitcpka=%t&serviceCert=%s&outboundHostname=%s&pathType=%s&reqPathSearch=%s&reqPathReplace=%s&templateFePath=%s&templateBePath=%s&timeoutServer=%s&timeoutClient=%s&timeoutTunnel=%s&reqMode=%s&httpsOnly=%t&httpsRedirectCode=%s&isDefaultBackend=%t&redirectWhenHttpProto=%t&httpsPort=%d&srcPort=%d&srcHttpsPort=%d&serviceDomain=%s&redirectFromDomain=%s&distribute=%t&sslVerifyNone=%t&serviceDomainAlgo=%s&addReqHeader=%s&addResHeader=%s&setReqHeader=%s&setResHeader=%s&delReqHeader=%s&delResHeader=%s&servicePath=/&servicePathExclude=%s&port=1234&connectionMode=%s&serviceHeader=X-Version:3,name:Viktor&allowedMethods=GET,DELETE&deniedMethods=PUT,POST&compressionAlgo=%s&compressionType=%s&checkResolvers=%t&replicas=%d&discoveryType=%s",
632+
"%s?serviceName=%s&users=%s&usersPassEncrypted=%t&aclName=%s&balanceGroup=%s&checkTcp=%t&clitcpka=%t&serviceCert=%s&outboundHostname=%s&pathType=%s&proxyInstanceName=%s&reqPathSearch=%s&reqPathReplace=%s&templateFePath=%s&templateBePath=%s&timeoutServer=%s&timeoutClient=%s&timeoutTunnel=%s&reqMode=%s&httpsOnly=%t&httpsRedirectCode=%s&isDefaultBackend=%t&redirectWhenHttpProto=%t&httpsPort=%d&srcPort=%d&srcHttpsPort=%d&serviceDomain=%s&redirectFromDomain=%s&distribute=%t&sslVerifyNone=%t&serviceDomainAlgo=%s&addReqHeader=%s&addResHeader=%s&setReqHeader=%s&setResHeader=%s&delReqHeader=%s&delResHeader=%s&servicePath=/&servicePathExclude=%s&port=1234&connectionMode=%s&serviceHeader=X-Version:3,name:Viktor&allowedMethods=GET,DELETE&deniedMethods=PUT,POST&compressionAlgo=%s&compressionType=%s&checkResolvers=%t&replicas=%d&discoveryType=%s",
632633

633634
s.BaseUrl,
634635
expected.ServiceName,
@@ -641,6 +642,7 @@ func (s *ServerTestSuite) Test_GetServiceFromUrl_ReturnsProxyService() {
641642
expected.ServiceCert,
642643
expected.ServiceDest[0].OutboundHostname,
643644
expected.PathType,
645+
expected.ProxyInstanceName,
644646
expected.ReqPathSearch,
645647
expected.ReqPathReplace,
646648
expected.TemplateFePath,

0 commit comments

Comments
 (0)