2018-01-04 14:56:03 +00:00
package consulcatalog
2017-12-04 19:02:15 +00:00
import (
"bytes"
2018-01-01 02:10:17 +00:00
"crypto/sha1"
"encoding/base64"
"math"
2017-12-04 19:02:15 +00:00
"sort"
"strconv"
"strings"
"text/template"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/provider/label"
"github.com/containous/traefik/types"
"github.com/hashicorp/consul/api"
)
2018-01-04 14:56:03 +00:00
func ( p * Provider ) buildConfiguration ( catalog [ ] catalogUpdate ) * types . Configuration {
2017-12-04 19:02:15 +00:00
var FuncMap = template . FuncMap {
2017-12-31 23:02:18 +00:00
"getAttribute" : p . getAttribute ,
"getTag" : getTag ,
"hasTag" : hasTag ,
// Backend functions
2018-01-02 17:21:38 +00:00
"getBackend" : getNodeBackendName , // Deprecated [breaking] getBackend -> getNodeBackendName
"getNodeBackendName" : getNodeBackendName ,
"getServiceBackendName" : getServiceBackendName ,
2017-12-04 19:02:15 +00:00
"getBackendAddress" : getBackendAddress ,
2018-01-01 02:10:17 +00:00
"getBackendName" : getServerName , // Deprecated [breaking] getBackendName -> getServerName
"getServerName" : getServerName ,
"hasMaxconnAttributes" : p . hasMaxConnAttributes , // Deprecated [breaking]
"getSticky" : p . getSticky , // Deprecated [breaking]
"hasStickinessLabel" : p . hasStickinessLabel , // Deprecated [breaking]
"getStickinessCookieName" : p . getStickinessCookieName , // Deprecated [breaking]
"getWeight" : p . getWeight , // Deprecated [breaking] Must replaced by a simple: "getWeight": p.getFuncIntAttribute(label.SuffixWeight, 0)
"getProtocol" : p . getFuncStringAttribute ( label . SuffixProtocol , label . DefaultProtocol ) ,
"getCircuitBreaker" : p . getCircuitBreaker ,
"getLoadBalancer" : p . getLoadBalancer ,
"getMaxConn" : p . getMaxConn ,
2018-01-01 02:49:06 +00:00
"getHealthCheck" : p . getHealthCheck ,
2017-12-31 23:02:18 +00:00
// Frontend functions
2018-01-01 02:37:24 +00:00
"getFrontendRule" : p . getFrontendRule ,
"getBasicAuth" : p . getFuncSliceAttribute ( label . SuffixFrontendAuthBasic ) ,
"getEntryPoints" : getEntryPoints , // Deprecated [breaking]
"getFrontEndEntryPoints" : p . getFuncSliceAttribute ( label . SuffixFrontendEntryPoints ) , // TODO [breaking] rename to getEntryPoints when getEntryPoints will be removed
"getPriority" : p . getFuncIntAttribute ( label . SuffixFrontendPriority , 0 ) ,
"getPassHostHeader" : p . getFuncBoolAttribute ( label . SuffixFrontendPassHostHeader , true ) ,
"getPassTLSCert" : p . getFuncBoolAttribute ( label . SuffixFrontendPassTLSCert , label . DefaultPassTLSCert ) ,
"getWhitelistSourceRange" : p . getFuncSliceAttribute ( label . SuffixFrontendWhitelistSourceRange ) ,
2018-01-01 03:03:29 +00:00
"getRedirect" : p . getRedirect ,
2018-01-01 03:38:10 +00:00
"hasErrorPages" : p . getFuncHasAttributePrefix ( label . BaseFrontendErrorPage ) ,
"getErrorPages" : p . getErrorPages ,
"hasRateLimit" : p . getFuncHasAttributePrefix ( label . BaseFrontendRateLimit ) ,
"getRateLimit" : p . getRateLimit ,
2018-01-02 17:32:53 +00:00
"getHeaders" : p . getHeaders ,
2017-12-04 19:02:15 +00:00
}
var allNodes [ ] * api . ServiceEntry
var services [ ] * serviceUpdate
for _ , info := range catalog {
if len ( info . Nodes ) > 0 {
services = append ( services , info . Service )
allNodes = append ( allNodes , info . Nodes ... )
}
}
// Ensure a stable ordering of nodes so that identical configurations may be detected
sort . Sort ( nodeSorter ( allNodes ) )
templateObjects := struct {
Services [ ] * serviceUpdate
Nodes [ ] * api . ServiceEntry
} {
Services : services ,
Nodes : allNodes ,
}
configuration , err := p . GetConfiguration ( "templates/consul_catalog.tmpl" , FuncMap , templateObjects )
if err != nil {
log . WithError ( err ) . Error ( "Failed to create config" )
}
return configuration
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) setupFrontEndRuleTemplate ( ) {
2017-12-04 19:02:15 +00:00
var FuncMap = template . FuncMap {
"getAttribute" : p . getAttribute ,
"getTag" : getTag ,
"hasTag" : hasTag ,
}
tmpl := template . New ( "consul catalog frontend rule" ) . Funcs ( FuncMap )
p . frontEndRuleTemplate = tmpl
}
2017-12-31 23:02:18 +00:00
// Specific functions
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getFrontendRule ( service serviceUpdate ) string {
2017-12-15 21:16:48 +00:00
customFrontendRule := p . getAttribute ( label . SuffixFrontendRule , service . Attributes , "" )
2017-12-04 19:02:15 +00:00
if customFrontendRule == "" {
customFrontendRule = p . FrontEndRule
}
tmpl := p . frontEndRuleTemplate
tmpl , err := tmpl . Parse ( customFrontendRule )
if err != nil {
log . Errorf ( "Failed to parse Consul Catalog custom frontend rule: %v" , err )
return ""
}
templateObjects := struct {
ServiceName string
Domain string
Attributes [ ] string
} {
ServiceName : service . ServiceName ,
Domain : p . Domain ,
Attributes : service . Attributes ,
}
var buffer bytes . Buffer
err = tmpl . Execute ( & buffer , templateObjects )
if err != nil {
log . Errorf ( "Failed to execute Consul Catalog custom frontend rule template: %v" , err )
return ""
}
return buffer . String ( )
}
2018-01-01 02:10:17 +00:00
// Deprecated
2018-01-04 14:56:03 +00:00
func ( p * Provider ) hasMaxConnAttributes ( attributes [ ] string ) bool {
2017-12-15 21:16:48 +00:00
amount := p . getAttribute ( label . SuffixBackendMaxConnAmount , attributes , "" )
2017-12-31 23:02:18 +00:00
extractorFunc := p . getAttribute ( label . SuffixBackendMaxConnExtractorFunc , attributes , "" )
return amount != "" && extractorFunc != ""
2017-12-04 19:02:15 +00:00
}
2017-12-31 23:02:18 +00:00
// Deprecated
2017-12-04 19:02:15 +00:00
func getEntryPoints ( list string ) [ ] string {
return strings . Split ( list , "," )
}
2018-01-02 17:21:38 +00:00
func getNodeBackendName ( node * api . ServiceEntry ) string {
2017-12-04 19:02:15 +00:00
return strings . ToLower ( node . Service . Service )
}
2018-01-02 17:21:38 +00:00
func getServiceBackendName ( service * serviceUpdate ) string {
return strings . ToLower ( service . ServiceName )
}
2017-12-04 19:02:15 +00:00
func getBackendAddress ( node * api . ServiceEntry ) string {
if node . Service . Address != "" {
return node . Service . Address
}
return node . Node . Address
}
2018-01-01 02:10:17 +00:00
func getServerName ( node * api . ServiceEntry , index int ) string {
serviceName := node . Service . Service + node . Service . Address + strconv . Itoa ( node . Service . Port )
// TODO sort tags ?
serviceName += strings . Join ( node . Service . Tags , "" )
2017-12-04 19:02:15 +00:00
2018-01-01 02:10:17 +00:00
hash := sha1 . New ( )
_ , err := hash . Write ( [ ] byte ( serviceName ) )
if err != nil {
// Impossible case
log . Error ( err )
} else {
serviceName = base64 . URLEncoding . EncodeToString ( hash . Sum ( nil ) )
2017-12-04 19:02:15 +00:00
}
// unique int at the end
2018-01-01 02:10:17 +00:00
return provider . Normalize ( node . Service . Service + "-" + strconv . Itoa ( index ) + "-" + serviceName )
2017-12-04 19:02:15 +00:00
}
// TODO: Deprecated
2017-12-31 23:02:18 +00:00
// replaced by Stickiness
// Deprecated
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getSticky ( tags [ ] string ) string {
2018-01-02 13:49:11 +00:00
stickyTag := p . getAttribute ( label . SuffixBackendLoadBalancerSticky , tags , "" )
2017-12-04 19:02:15 +00:00
if len ( stickyTag ) > 0 {
log . Warnf ( "Deprecated configuration found: %s. Please use %s." , label . TraefikBackendLoadBalancerSticky , label . TraefikBackendLoadBalancerStickiness )
} else {
stickyTag = "false"
}
return stickyTag
}
2018-01-01 02:10:17 +00:00
// Deprecated
2018-01-04 14:56:03 +00:00
func ( p * Provider ) hasStickinessLabel ( tags [ ] string ) bool {
2018-01-02 13:49:11 +00:00
stickinessTag := p . getAttribute ( label . SuffixBackendLoadBalancerStickiness , tags , "" )
2017-12-04 19:02:15 +00:00
return len ( stickinessTag ) > 0 && strings . EqualFold ( strings . TrimSpace ( stickinessTag ) , "true" )
}
2018-01-01 02:10:17 +00:00
// Deprecated
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getStickinessCookieName ( tags [ ] string ) string {
2018-01-02 13:49:11 +00:00
return p . getAttribute ( label . SuffixBackendLoadBalancerStickinessCookieName , tags , "" )
2017-12-04 19:02:15 +00:00
}
2017-12-31 23:02:18 +00:00
2018-01-01 02:10:17 +00:00
// Deprecated
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getWeight ( tags [ ] string ) int {
2018-01-01 02:10:17 +00:00
weight := p . getIntAttribute ( label . SuffixWeight , tags , 0 )
// Deprecated
deprecatedWeightTag := "backend." + label . SuffixWeight
if p . hasAttribute ( deprecatedWeightTag , tags ) {
log . Warnf ( "Deprecated configuration found: %s. Please use %s." ,
p . getPrefixedName ( deprecatedWeightTag ) , p . getPrefixedName ( label . SuffixWeight ) )
weight = p . getIntAttribute ( deprecatedWeightTag , tags , 0 )
}
return weight
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getCircuitBreaker ( tags [ ] string ) * types . CircuitBreaker {
2018-01-01 02:10:17 +00:00
circuitBreaker := p . getAttribute ( label . SuffixBackendCircuitBreakerExpression , tags , "" )
if p . hasAttribute ( label . SuffixBackendCircuitBreaker , tags ) {
log . Warnf ( "Deprecated configuration found: %s. Please use %s." ,
p . getPrefixedName ( label . SuffixBackendCircuitBreaker ) , p . getPrefixedName ( label . SuffixBackendCircuitBreakerExpression ) )
circuitBreaker = p . getAttribute ( label . SuffixBackendCircuitBreaker , tags , "" )
}
if len ( circuitBreaker ) == 0 {
return nil
}
return & types . CircuitBreaker { Expression : circuitBreaker }
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getLoadBalancer ( tags [ ] string ) * types . LoadBalancer {
2018-01-01 02:10:17 +00:00
rawSticky := p . getSticky ( tags )
sticky , err := strconv . ParseBool ( rawSticky )
if err != nil {
log . Debugf ( "Invalid sticky value: %s" , rawSticky )
sticky = false
}
method := p . getAttribute ( label . SuffixBackendLoadBalancerMethod , tags , label . DefaultBackendLoadBalancerMethod )
// Deprecated
deprecatedMethodTag := "backend.loadbalancer"
if p . hasAttribute ( deprecatedMethodTag , tags ) {
log . Warnf ( "Deprecated configuration found: %s. Please use %s." ,
p . getPrefixedName ( deprecatedMethodTag ) , p . getPrefixedName ( label . SuffixWeight ) )
method = p . getAttribute ( deprecatedMethodTag , tags , label . SuffixBackendLoadBalancerMethod )
}
lb := & types . LoadBalancer {
Method : method ,
Sticky : sticky ,
}
if p . getBoolAttribute ( label . SuffixBackendLoadBalancerStickiness , tags , false ) {
lb . Stickiness = & types . Stickiness {
CookieName : p . getAttribute ( label . SuffixBackendLoadBalancerStickinessCookieName , tags , "" ) ,
}
}
return lb
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getMaxConn ( tags [ ] string ) * types . MaxConn {
2018-01-01 02:10:17 +00:00
amount := p . getInt64Attribute ( label . SuffixBackendMaxConnAmount , tags , math . MinInt64 )
extractorFunc := p . getAttribute ( label . SuffixBackendMaxConnExtractorFunc , tags , label . DefaultBackendMaxconnExtractorFunc )
if amount == math . MinInt64 || len ( extractorFunc ) == 0 {
return nil
}
return & types . MaxConn {
Amount : amount ,
ExtractorFunc : extractorFunc ,
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getHealthCheck ( tags [ ] string ) * types . HealthCheck {
2018-01-01 02:49:06 +00:00
path := p . getAttribute ( label . SuffixBackendHealthCheckPath , tags , "" )
if len ( path ) == 0 {
return nil
}
port := p . getIntAttribute ( label . SuffixBackendHealthCheckPort , tags , label . DefaultBackendHealthCheckPort )
interval := p . getAttribute ( label . SuffixBackendHealthCheckInterval , tags , "" )
return & types . HealthCheck {
Path : path ,
Port : port ,
Interval : interval ,
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getRedirect ( tags [ ] string ) * types . Redirect {
2018-01-01 03:03:29 +00:00
if p . hasAttribute ( label . SuffixFrontendRedirectEntryPoint , tags ) {
return & types . Redirect {
EntryPoint : p . getAttribute ( label . SuffixFrontendRedirectEntryPoint , tags , "" ) ,
}
}
if p . hasAttribute ( label . SuffixFrontendRedirectRegex , tags ) && p . hasAttribute ( label . SuffixFrontendRedirectReplacement , tags ) {
return & types . Redirect {
Regex : p . getAttribute ( label . SuffixFrontendRedirectRegex , tags , "" ) ,
Replacement : p . getAttribute ( label . SuffixFrontendRedirectReplacement , tags , "" ) ,
}
}
return nil
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getErrorPages ( tags [ ] string ) map [ string ] * types . ErrorPage {
2018-01-01 03:38:10 +00:00
labels := p . parseTagsToNeutralLabels ( tags )
prefix := label . Prefix + label . BaseFrontendErrorPage
return label . ParseErrorPages ( labels , prefix , label . RegexpFrontendErrorPage )
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getRateLimit ( tags [ ] string ) * types . RateLimit {
2018-01-01 03:38:10 +00:00
extractorFunc := p . getAttribute ( label . SuffixFrontendRateLimitExtractorFunc , tags , "" )
if len ( extractorFunc ) == 0 {
return nil
}
labels := p . parseTagsToNeutralLabels ( tags )
prefix := label . Prefix + label . BaseFrontendRateLimit
limits := label . ParseRateSets ( labels , prefix , label . RegexpFrontendRateLimit )
return & types . RateLimit {
ExtractorFunc : extractorFunc ,
RateSet : limits ,
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getHeaders ( tags [ ] string ) * types . Headers {
2018-01-02 17:32:53 +00:00
headers := & types . Headers {
CustomRequestHeaders : p . getMapAttribute ( label . SuffixFrontendRequestHeaders , tags ) ,
CustomResponseHeaders : p . getMapAttribute ( label . SuffixFrontendResponseHeaders , tags ) ,
SSLProxyHeaders : p . getMapAttribute ( label . SuffixFrontendHeadersSSLProxyHeaders , tags ) ,
AllowedHosts : p . getSliceAttribute ( label . SuffixFrontendHeadersAllowedHosts , tags ) ,
HostsProxyHeaders : p . getSliceAttribute ( label . SuffixFrontendHeadersHostsProxyHeaders , tags ) ,
SSLHost : p . getAttribute ( label . SuffixFrontendHeadersSSLHost , tags , "" ) ,
CustomFrameOptionsValue : p . getAttribute ( label . SuffixFrontendHeadersCustomFrameOptionsValue , tags , "" ) ,
ContentSecurityPolicy : p . getAttribute ( label . SuffixFrontendHeadersContentSecurityPolicy , tags , "" ) ,
PublicKey : p . getAttribute ( label . SuffixFrontendHeadersPublicKey , tags , "" ) ,
ReferrerPolicy : p . getAttribute ( label . SuffixFrontendHeadersReferrerPolicy , tags , "" ) ,
STSSeconds : p . getInt64Attribute ( label . SuffixFrontendHeadersSTSSeconds , tags , 0 ) ,
SSLRedirect : p . getBoolAttribute ( label . SuffixFrontendHeadersSSLRedirect , tags , false ) ,
SSLTemporaryRedirect : p . getBoolAttribute ( label . SuffixFrontendHeadersSSLTemporaryRedirect , tags , false ) ,
STSIncludeSubdomains : p . getBoolAttribute ( label . SuffixFrontendHeadersSTSIncludeSubdomains , tags , false ) ,
STSPreload : p . getBoolAttribute ( label . SuffixFrontendHeadersSTSPreload , tags , false ) ,
ForceSTSHeader : p . getBoolAttribute ( label . SuffixFrontendHeadersForceSTSHeader , tags , false ) ,
FrameDeny : p . getBoolAttribute ( label . SuffixFrontendHeadersFrameDeny , tags , false ) ,
ContentTypeNosniff : p . getBoolAttribute ( label . SuffixFrontendHeadersContentTypeNosniff , tags , false ) ,
BrowserXSSFilter : p . getBoolAttribute ( label . SuffixFrontendHeadersBrowserXSSFilter , tags , false ) ,
IsDevelopment : p . getBoolAttribute ( label . SuffixFrontendHeadersIsDevelopment , tags , false ) ,
}
if ! headers . HasSecureHeadersDefined ( ) && ! headers . HasCustomHeadersDefined ( ) {
return nil
}
return headers
}
2017-12-31 23:02:18 +00:00
// Base functions
2018-01-04 14:56:03 +00:00
func ( p * Provider ) parseTagsToNeutralLabels ( tags [ ] string ) map [ string ] string {
2018-01-01 03:38:10 +00:00
var labels map [ string ] string
for _ , tag := range tags {
if strings . HasPrefix ( tag , p . Prefix ) {
parts := strings . SplitN ( tag , "=" , 2 )
if len ( parts ) == 2 {
if labels == nil {
labels = make ( map [ string ] string )
}
// replace custom prefix by the generic prefix
key := label . Prefix + strings . TrimPrefix ( parts [ 0 ] , p . Prefix + "." )
labels [ key ] = parts [ 1 ]
}
}
}
return labels
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getFuncStringAttribute ( name string , defaultValue string ) func ( tags [ ] string ) string {
2018-01-01 02:10:17 +00:00
return func ( tags [ ] string ) string {
return p . getAttribute ( name , tags , defaultValue )
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getFuncSliceAttribute ( name string ) func ( tags [ ] string ) [ ] string {
2018-01-01 02:10:17 +00:00
return func ( tags [ ] string ) [ ] string {
return p . getSliceAttribute ( name , tags )
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getMapAttribute ( name string , tags [ ] string ) map [ string ] string {
2018-01-02 17:32:53 +00:00
rawValue := getTag ( p . getPrefixedName ( name ) , tags , "" )
if len ( rawValue ) == 0 {
return nil
}
return label . ParseMapValue ( p . getPrefixedName ( name ) , rawValue )
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getFuncIntAttribute ( name string , defaultValue int ) func ( tags [ ] string ) int {
2018-01-01 02:10:17 +00:00
return func ( tags [ ] string ) int {
return p . getIntAttribute ( name , tags , defaultValue )
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getFuncBoolAttribute ( name string , defaultValue bool ) func ( tags [ ] string ) bool {
2018-01-01 02:10:17 +00:00
return func ( tags [ ] string ) bool {
return p . getBoolAttribute ( name , tags , defaultValue )
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getFuncHasAttributePrefix ( name string ) func ( tags [ ] string ) bool {
2018-01-01 03:38:10 +00:00
return func ( tags [ ] string ) bool {
return p . hasAttributePrefix ( name , tags )
}
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getInt64Attribute ( name string , tags [ ] string , defaultValue int64 ) int64 {
2018-01-01 02:10:17 +00:00
rawValue := getTag ( p . getPrefixedName ( name ) , tags , "" )
if len ( rawValue ) == 0 {
return defaultValue
}
value , err := strconv . ParseInt ( rawValue , 10 , 64 )
if err != nil {
log . Errorf ( "Invalid value for %s: %s" , name , rawValue )
return defaultValue
}
return value
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getIntAttribute ( name string , tags [ ] string , defaultValue int ) int {
2018-01-01 02:10:17 +00:00
rawValue := getTag ( p . getPrefixedName ( name ) , tags , "" )
if len ( rawValue ) == 0 {
return defaultValue
}
value , err := strconv . Atoi ( rawValue )
if err != nil {
log . Errorf ( "Invalid value for %s: %s" , name , rawValue )
return defaultValue
}
return value
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getSliceAttribute ( name string , tags [ ] string ) [ ] string {
2017-12-31 23:02:18 +00:00
rawValue := getTag ( p . getPrefixedName ( name ) , tags , "" )
if len ( rawValue ) == 0 {
return nil
}
return label . SplitAndTrimString ( rawValue , "," )
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getBoolAttribute ( name string , tags [ ] string , defaultValue bool ) bool {
2017-12-31 23:02:18 +00:00
rawValue := getTag ( p . getPrefixedName ( name ) , tags , "" )
if len ( rawValue ) == 0 {
return defaultValue
}
value , err := strconv . ParseBool ( rawValue )
if err != nil {
log . Errorf ( "Invalid value for %s: %s" , name , rawValue )
return defaultValue
}
return value
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) hasAttribute ( name string , tags [ ] string ) bool {
2018-01-01 03:03:29 +00:00
return hasTag ( p . getPrefixedName ( name ) , tags )
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) hasAttributePrefix ( name string , tags [ ] string ) bool {
2018-01-01 03:38:10 +00:00
return hasTagPrefix ( p . getPrefixedName ( name ) , tags )
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getAttribute ( name string , tags [ ] string , defaultValue string ) string {
2017-12-31 23:02:18 +00:00
return getTag ( p . getPrefixedName ( name ) , tags , defaultValue )
}
2018-01-04 14:56:03 +00:00
func ( p * Provider ) getPrefixedName ( name string ) string {
2017-12-31 23:02:18 +00:00
if len ( p . Prefix ) > 0 && len ( name ) > 0 {
return p . Prefix + "." + name
}
return name
}
func hasTag ( name string , tags [ ] string ) bool {
lowerName := strings . ToLower ( name )
for _ , tag := range tags {
lowerTag := strings . ToLower ( tag )
// Given the nature of Consul tags, which could be either singular markers, or key=value pairs
if strings . HasPrefix ( lowerTag , lowerName + "=" ) || lowerTag == lowerName {
return true
}
}
return false
}
2018-01-01 03:38:10 +00:00
func hasTagPrefix ( name string , tags [ ] string ) bool {
lowerName := strings . ToLower ( name )
for _ , tag := range tags {
lowerTag := strings . ToLower ( tag )
if strings . HasPrefix ( lowerTag , lowerName ) {
return true
}
}
return false
}
2017-12-31 23:02:18 +00:00
func getTag ( name string , tags [ ] string , defaultValue string ) string {
lowerName := strings . ToLower ( name )
for _ , tag := range tags {
lowerTag := strings . ToLower ( tag )
// Given the nature of Consul tags, which could be either singular markers, or key=value pairs
if strings . HasPrefix ( lowerTag , lowerName + "=" ) || lowerTag == lowerName {
// In case, where a tag might be a key=value, try to split it by the first '='
kv := strings . SplitN ( tag , "=" , 2 )
// If the returned result is a key=value pair, return the 'value' component
if len ( kv ) == 2 {
return kv [ 1 ]
}
// If the returned result is a singular marker, return the 'key' component
return kv [ 0 ]
}
}
return defaultValue
}