New entry point parser.

This commit is contained in:
Ludovic Fernandez 2017-10-13 15:04:02 +02:00 committed by Traefiker
parent 8af39bdaf7
commit 9598f646f5
2 changed files with 82 additions and 58 deletions

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"regexp"
"strings" "strings"
"time" "time"
@ -193,55 +192,52 @@ func (ep *EntryPoints) String() string {
// Set's argument is a string to be parsed to set the flag. // Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it. // It's a comma-separated list, so we split it.
func (ep *EntryPoints) Set(value string) error { func (ep *EntryPoints) Set(value string) error {
result, err := parseEntryPointsConfiguration(value) result := parseEntryPointsConfiguration(value)
if err != nil {
return err
}
var configTLS *TLS var configTLS *TLS
if len(result["TLS"]) > 0 { if len(result["tls"]) > 0 {
certs := Certificates{} certs := Certificates{}
if err := certs.Set(result["TLS"]); err != nil { if err := certs.Set(result["tls"]); err != nil {
return err return err
} }
configTLS = &TLS{ configTLS = &TLS{
Certificates: certs, Certificates: certs,
} }
} else if len(result["TLSACME"]) > 0 { } else if len(result["tls_acme"]) > 0 {
configTLS = &TLS{ configTLS = &TLS{
Certificates: Certificates{}, Certificates: Certificates{},
} }
} }
if len(result["CA"]) > 0 { if len(result["ca"]) > 0 {
files := strings.Split(result["CA"], ",") files := strings.Split(result["ca"], ",")
configTLS.ClientCAFiles = files configTLS.ClientCAFiles = files
} }
var redirect *Redirect var redirect *Redirect
if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 { if len(result["redirect_entrypoint"]) > 0 || len(result["redirect_regex"]) > 0 || len(result["redirect_replacement"]) > 0 {
redirect = &Redirect{ redirect = &Redirect{
EntryPoint: result["RedirectEntryPoint"], EntryPoint: result["redirect_entrypoint"],
Regex: result["RedirectRegex"], Regex: result["redirect_regex"],
Replacement: result["RedirectReplacement"], Replacement: result["redirect_replacement"],
} }
} }
whiteListSourceRange := []string{} whiteListSourceRange := []string{}
if len(result["WhiteListSourceRange"]) > 0 { if len(result["whitelistsourcerange"]) > 0 {
whiteListSourceRange = strings.Split(result["WhiteListSourceRange"], ",") whiteListSourceRange = strings.Split(result["whitelistsourcerange"], ",")
} }
compress := toBool(result, "Compress") compress := toBool(result, "compress")
var proxyProtocol *ProxyProtocol var proxyProtocol *ProxyProtocol
if len(result["ProxyProtocol"]) > 0 { if len(result["proxyprotocol_trustedips"]) > 0 {
trustedIPs := strings.Split(result["ProxyProtocol"], ",") trustedIPs := strings.Split(result["proxyprotocol_trustedips"], ",")
proxyProtocol = &ProxyProtocol{ proxyProtocol = &ProxyProtocol{
TrustedIPs: trustedIPs, TrustedIPs: trustedIPs,
} }
} }
(*ep)[result["Name"]] = &EntryPoint{ (*ep)[result["name"]] = &EntryPoint{
Address: result["Address"], Address: result["address"],
TLS: configTLS, TLS: configTLS,
Redirect: redirect, Redirect: redirect,
Compress: compress, Compress: compress,
@ -252,20 +248,24 @@ func (ep *EntryPoints) Set(value string) error {
return nil return nil
} }
func parseEntryPointsConfiguration(value string) (map[string]string, error) { func parseEntryPointsConfiguration(raw string) map[string]string {
regex := regexp.MustCompile(`(?:Name:(?P<Name>\S*))\s*(?:Address:(?P<Address>\S*))?\s*(?:TLS:(?P<TLS>\S*))?\s*(?P<TLSACME>TLS)?\s*(?:CA:(?P<CA>\S*))?\s*(?:Redirect\.EntryPoint:(?P<RedirectEntryPoint>\S*))?\s*(?:Redirect\.Regex:(?P<RedirectRegex>\S*))?\s*(?:Redirect\.Replacement:(?P<RedirectReplacement>\S*))?\s*(?:Compress:(?P<Compress>\S*))?\s*(?:WhiteListSourceRange:(?P<WhiteListSourceRange>\S*))?\s*(?:ProxyProtocol\.TrustedIPs:(?P<ProxyProtocol>\S*))?`) sections := strings.Fields(raw)
match := regex.FindAllStringSubmatch(value, -1)
if match == nil { config := make(map[string]string)
return nil, fmt.Errorf("bad EntryPoints format: %s", value) for _, part := range sections {
} field := strings.SplitN(part, ":", 2)
matchResult := match[0] name := strings.ToLower(strings.Replace(field[0], ".", "_", -1))
result := make(map[string]string) if len(field) > 1 {
for i, name := range regex.SubexpNames() { config[name] = field[1]
if i != 0 && len(matchResult[i]) != 0 { } else {
result[name] = matchResult[i] if strings.EqualFold(name, "TLS") {
config["tls_acme"] = "TLS"
} else {
config[name] = ""
} }
} }
return result, nil }
return config
} }
func toBool(conf map[string]string, key string) bool { func toBool(conf map[string]string, key string) bool {

View file

@ -16,36 +16,36 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
}{ }{
{ {
name: "all parameters", name: "all parameters",
value: "Name:foo Address:bar TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1", value: "Name:foo TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1 Address::8000",
expectedResult: map[string]string{ expectedResult: map[string]string{
"Name": "foo", "name": "foo",
"Address": "bar", "address": ":8000",
"CA": "car", "ca": "car",
"TLS": "goo", "tls": "goo",
"TLSACME": "TLS", "tls_acme": "TLS",
"RedirectEntryPoint": "RedirectEntryPoint", "redirect_entrypoint": "RedirectEntryPoint",
"RedirectRegex": "RedirectRegex", "redirect_regex": "RedirectRegex",
"RedirectReplacement": "RedirectReplacement", "redirect_replacement": "RedirectReplacement",
"WhiteListSourceRange": "WhiteListSourceRange", "whitelistsourcerange": "WhiteListSourceRange",
"ProxyProtocol": "192.168.0.1", "proxyprotocol_trustedips": "192.168.0.1",
"Compress": "true", "compress": "true",
}, },
}, },
{ {
name: "compress on", name: "compress on",
value: "Name:foo Compress:on", value: "name:foo Compress:on",
expectedResult: map[string]string{ expectedResult: map[string]string{
"Name": "foo", "name": "foo",
"Compress": "on", "compress": "on",
}, },
}, },
{ {
name: "TLS", name: "TLS",
value: "Name:foo TLS:goo TLS", value: "Name:foo TLS:goo TLS",
expectedResult: map[string]string{ expectedResult: map[string]string{
"Name": "foo", "name": "foo",
"TLS": "goo", "tls": "goo",
"TLSACME": "TLS", "tls_acme": "TLS",
}, },
}, },
} }
@ -55,10 +55,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
t.Parallel() t.Parallel()
conf, err := parseEntryPointsConfiguration(test.value) conf := parseEntryPointsConfiguration(test.value)
if err != nil {
t.Error(err)
}
for key, value := range conf { for key, value := range conf {
fmt.Println(key, value) fmt.Println(key, value)
@ -133,11 +130,38 @@ func TestEntryPoints_Set(t *testing.T) {
expectedEntryPoint *EntryPoint expectedEntryPoint *EntryPoint
}{ }{
{ {
name: "all parameters", name: "all parameters camelcase",
expression: "Name:foo Address:bar TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1", expression: "Name:foo Address::8000 TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1",
expectedEntryPointName: "foo", expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Address: "bar", Address: ":8000",
Redirect: &Redirect{
EntryPoint: "RedirectEntryPoint",
Regex: "RedirectRegex",
Replacement: "RedirectReplacement",
},
Compress: true,
ProxyProtocol: &ProxyProtocol{
TrustedIPs: []string{"192.168.0.1"},
},
WhitelistSourceRange: []string{"Range"},
TLS: &TLS{
ClientCAFiles: []string{"car"},
Certificates: Certificates{
{
CertFile: FileOrContent("goo"),
KeyFile: FileOrContent("gii"),
},
},
},
},
},
{
name: "all parameters lowercase",
expression: "name:foo address::8000 tls:goo,gii tls ca:car redirect.entryPoint:RedirectEntryPoint redirect.regex:RedirectRegex redirect.replacement:RedirectReplacement compress:true whiteListSourceRange:Range proxyProtocol.TrustedIPs:192.168.0.1",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: ":8000",
Redirect: &Redirect{ Redirect: &Redirect{
EntryPoint: "RedirectEntryPoint", EntryPoint: "RedirectEntryPoint",
Regex: "RedirectRegex", Regex: "RedirectRegex",