2018-03-22 16:42:03 +00:00
|
|
|
package servicefabric
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
"text/template"
|
|
|
|
|
|
|
|
"github.com/containous/traefik/log"
|
|
|
|
"github.com/containous/traefik/provider"
|
|
|
|
"github.com/containous/traefik/provider/label"
|
|
|
|
"github.com/containous/traefik/types"
|
|
|
|
sf "github.com/jjcollinge/servicefabric"
|
|
|
|
)
|
|
|
|
|
2018-04-13 13:44:04 +00:00
|
|
|
func (p *Provider) buildConfiguration(services []ServiceItemExtended) (*types.Configuration, error) {
|
2018-03-26 14:20:37 +00:00
|
|
|
var sfFuncMap = template.FuncMap{
|
2018-03-22 16:42:03 +00:00
|
|
|
// Services
|
|
|
|
"getServices": getServices,
|
|
|
|
"hasLabel": hasService,
|
|
|
|
"getLabelValue": getServiceStringLabel,
|
|
|
|
"getLabelsWithPrefix": getServiceLabelsWithPrefix,
|
|
|
|
"isPrimary": isPrimary,
|
|
|
|
"isStateful": isStateful,
|
|
|
|
"isStateless": isStateless,
|
|
|
|
"isEnabled": getFuncBoolLabel(label.TraefikEnable, false),
|
|
|
|
"getBackendName": getBackendName,
|
|
|
|
"getDefaultEndpoint": getDefaultEndpoint,
|
|
|
|
"getNamedEndpoint": getNamedEndpoint, // FIXME unused
|
|
|
|
"getApplicationParameter": getApplicationParameter, // FIXME unused
|
|
|
|
"doesAppParamContain": doesAppParamContain, // FIXME unused
|
|
|
|
"filterServicesByLabelValue": filterServicesByLabelValue, // FIXME unused
|
|
|
|
|
|
|
|
// Backend functions
|
2018-04-17 09:18:04 +00:00
|
|
|
"getWeight": getFuncServiceIntLabel(label.TraefikWeight, label.DefaultWeight),
|
2018-03-22 16:42:03 +00:00
|
|
|
"getProtocol": getFuncServiceStringLabel(label.TraefikProtocol, label.DefaultProtocol),
|
|
|
|
"getMaxConn": getMaxConn,
|
|
|
|
"getHealthCheck": getHealthCheck,
|
|
|
|
"getCircuitBreaker": getCircuitBreaker,
|
|
|
|
"getLoadBalancer": getLoadBalancer,
|
|
|
|
|
|
|
|
// Frontend Functions
|
2018-04-17 09:18:04 +00:00
|
|
|
"getPriority": getFuncServiceIntLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
|
|
|
"getPassHostHeader": getFuncServiceBoolLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
|
|
|
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
|
2018-03-26 14:20:37 +00:00
|
|
|
"getEntryPoints": getFuncServiceSliceStringLabel(label.TraefikFrontendEntryPoints),
|
|
|
|
"getBasicAuth": getFuncServiceSliceStringLabel(label.TraefikFrontendAuthBasic),
|
|
|
|
"getFrontendRules": getFuncServiceLabelWithPrefix(label.TraefikFrontendRule),
|
|
|
|
"getWhiteList": getWhiteList,
|
|
|
|
"getHeaders": getHeaders,
|
|
|
|
"getRedirect": getRedirect,
|
2018-03-22 16:42:03 +00:00
|
|
|
|
|
|
|
// SF Service Grouping
|
|
|
|
"getGroupedServices": getFuncServicesGroupedByLabel(traefikSFGroupName),
|
|
|
|
"getGroupedWeight": getFuncServiceStringLabel(traefikSFGroupWeight, "1"),
|
|
|
|
}
|
|
|
|
|
|
|
|
templateObjects := struct {
|
|
|
|
Services []ServiceItemExtended
|
|
|
|
}{
|
|
|
|
Services: services,
|
|
|
|
}
|
|
|
|
|
|
|
|
return p.GetConfiguration(tmpl, sfFuncMap, templateObjects)
|
|
|
|
}
|
|
|
|
|
2018-04-13 13:44:04 +00:00
|
|
|
func isPrimary(instance replicaInstance) bool {
|
|
|
|
_, data := instance.GetReplicaData()
|
|
|
|
return data.ReplicaRole == "Primary"
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getBackendName(service ServiceItemExtended, partition PartitionItemExtended) string {
|
|
|
|
return provider.Normalize(service.Name + partition.PartitionInformation.ID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getDefaultEndpoint(instance replicaInstance) string {
|
|
|
|
id, data := instance.GetReplicaData()
|
|
|
|
endpoint, err := getReplicaDefaultEndpoint(data)
|
|
|
|
if err != nil {
|
2018-07-11 07:08:03 +00:00
|
|
|
log.Warnf("No default endpoint for replica %s in service %s endpointData: %s", id, data.Address, err)
|
2018-03-22 16:42:03 +00:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return endpoint
|
|
|
|
}
|
|
|
|
|
|
|
|
func getNamedEndpoint(instance replicaInstance, endpointName string) string {
|
|
|
|
id, data := instance.GetReplicaData()
|
|
|
|
endpoint, err := getReplicaNamedEndpoint(data, endpointName)
|
|
|
|
if err != nil {
|
|
|
|
log.Warnf("No names endpoint of %s for replica %s in endpointData: %s. Error: %v", endpointName, id, data.Address, err)
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return endpoint
|
|
|
|
}
|
|
|
|
|
|
|
|
func getReplicaNamedEndpoint(replicaData *sf.ReplicaItemBase, endpointName string) (string, error) {
|
|
|
|
endpoints, err := decodeEndpointData(replicaData.Address)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
endpoint, exists := endpoints[endpointName]
|
|
|
|
if !exists {
|
|
|
|
return "", errors.New("endpoint doesn't exist")
|
|
|
|
}
|
|
|
|
return endpoint, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func getApplicationParameter(app sf.ApplicationItem, key string) string {
|
|
|
|
for _, param := range app.Parameters {
|
|
|
|
if param.Key == key {
|
|
|
|
return param.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Errorf("Parameter %s doesn't exist in app %s", key, app.Name)
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func getServices(services []ServiceItemExtended, key string) map[string][]ServiceItemExtended {
|
|
|
|
result := map[string][]ServiceItemExtended{}
|
|
|
|
for _, service := range services {
|
|
|
|
if value, exists := service.Labels[key]; exists {
|
|
|
|
if matchingServices, hasKeyAlready := result[value]; hasKeyAlready {
|
|
|
|
result[value] = append(matchingServices, service)
|
|
|
|
} else {
|
|
|
|
result[value] = []ServiceItemExtended{service}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func doesAppParamContain(app sf.ApplicationItem, key, shouldContain string) bool {
|
|
|
|
value := getApplicationParameter(app, key)
|
|
|
|
return strings.Contains(value, shouldContain)
|
|
|
|
}
|
|
|
|
|
|
|
|
func filterServicesByLabelValue(services []ServiceItemExtended, key, expectedValue string) []ServiceItemExtended {
|
|
|
|
var srvWithLabel []ServiceItemExtended
|
|
|
|
for _, service := range services {
|
|
|
|
value, exists := service.Labels[key]
|
|
|
|
if exists && value == expectedValue {
|
|
|
|
srvWithLabel = append(srvWithLabel, service)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return srvWithLabel
|
|
|
|
}
|
|
|
|
|
|
|
|
func getHeaders(service ServiceItemExtended) *types.Headers {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetHeaders(service.Labels)
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 14:20:37 +00:00
|
|
|
func getWhiteList(service ServiceItemExtended) *types.WhiteList {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetWhiteList(service.Labels)
|
2018-03-26 14:20:37 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 16:42:03 +00:00
|
|
|
func getRedirect(service ServiceItemExtended) *types.Redirect {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetRedirect(service.Labels)
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getMaxConn(service ServiceItemExtended) *types.MaxConn {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetMaxConn(service.Labels)
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getHealthCheck(service ServiceItemExtended) *types.HealthCheck {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetHealthCheck(service.Labels)
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getCircuitBreaker(service ServiceItemExtended) *types.CircuitBreaker {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetCircuitBreaker(service.Labels)
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getLoadBalancer(service ServiceItemExtended) *types.LoadBalancer {
|
2018-04-17 09:18:04 +00:00
|
|
|
return label.GetLoadBalancer(service.Labels)
|
2018-03-22 16:42:03 +00:00
|
|
|
}
|