Update Service Fabric backend.
This commit is contained in:
parent
1b410980ca
commit
0fa0c2256a
10 changed files with 677 additions and 352 deletions
9
Gopkg.lock
generated
9
Gopkg.lock
generated
|
@ -247,8 +247,8 @@
|
|||
[[projects]]
|
||||
name = "github.com/containous/traefik-extra-service-fabric"
|
||||
packages = ["."]
|
||||
revision = "ca1fb57108293caad285b1c366b763f6c6ab71c9"
|
||||
version = "v1.0.5"
|
||||
revision = "a0b20089e99069884b060875fc015c13a23e7953"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/coreos/bbolt"
|
||||
|
@ -745,10 +745,9 @@
|
|||
version = "v1.3.7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jjcollinge/servicefabric"
|
||||
packages = ["."]
|
||||
revision = "8026935326c842b71dee8e2329c1fda41a7a92f4"
|
||||
revision = "8eebe170fa1ba25d3dfb928b3f86a7313b13b9fe"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jmespath/go-jmespath"
|
||||
|
@ -1633,6 +1632,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "39b400d9928cce714a46cae410074fd2622a097a9e0faba76a7b21537fabd728"
|
||||
inputs-digest = "ab328aeda9dbd2c4dc87061c25dbfbd151dbdc5946b6f512f676b39bebba8d8e"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
[[constraint]]
|
||||
name = "github.com/containous/traefik-extra-service-fabric"
|
||||
version = "1.0.5"
|
||||
version = "1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/coreos/go-systemd"
|
||||
|
|
|
@ -69,10 +69,10 @@ Here is an example of an extension setting Træfik labels:
|
|||
</StatelessServiceType>
|
||||
```
|
||||
|
||||
#### Property Manager
|
||||
#### Property Manager
|
||||
|
||||
Set Labels with the property manager API to overwrite and add labels, while your service is running.
|
||||
Here is an example of adding a frontend rule using the property manager API.
|
||||
Here is an example of adding a frontend rule using the property manager API.
|
||||
|
||||
```shell
|
||||
curl -X PUT \
|
||||
|
@ -92,23 +92,63 @@ curl -X PUT \
|
|||
|
||||
## Available Labels
|
||||
|
||||
Labels, set through extensions or the property manager, can be used on services to override default behaviour.
|
||||
Labels, set through extensions or the property manager, can be used on services to override default behavior.
|
||||
|
||||
| Label | Description |
|
||||
|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `traefik.backend.maxconn.amount=10` | Set a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect. |
|
||||
| `traefik.backend.maxconn.extractorfunc=client.ip` | Set the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect. |
|
||||
| `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm |
|
||||
| `traefik.backend.loadbalancer.stickiness=true` | Enable backend sticky sessions |
|
||||
| `traefik.backend.loadbalancer.stickiness.cookieName=NAME` | Manually set the cookie name for sticky sessions |
|
||||
| `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend |
|
||||
| `traefik.backend.weight=10` | Assign this weight to the container |
|
||||
| `traefik.expose=true` | Expose this service using træfik |
|
||||
| `traefik.frontend.rule=EXPR` | Override the default frontend rule. Defaults to SF address. |
|
||||
| `traefik.frontend.passHostHeader=true` | Forward client `Host` header to the backend. |
|
||||
| `traefik.frontend.priority=10` | Override default frontend priority |
|
||||
| `traefik.frontend.entryPoints=http,https` | Assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints` |
|
||||
| `traefik.frontend.auth.basic=EXPR` | Set basic authentication for that frontend in CSV format: `User:Hash,User:Hash` |
|
||||
| `traefik.frontend.whitelistSourceRange:RANGE` | List of IP-Ranges which are allowed to access. An unset or empty list allows all Source-IPs to access.<br>If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. |
|
||||
| `traefik.backend.group.name` | Group all services with the same name into a single backend in Træfik |
|
||||
| `traefik.backend.group.weight` | Set the weighting of the current services nodes in the backend group |
|
||||
| Label | Description |
|
||||
|------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `traefik.enable=false` | Disable this container in Træfik |
|
||||
| `traefik.backend.circuitbreaker.expression=EXPR` | Create a [circuit breaker](/basics/#backends) to be used against the backend |
|
||||
| `traefik.backend.group.name` | Group all services with the same name into a single backend in Træfik |
|
||||
| `traefik.backend.group.weight` | Set the weighting of the current services nodes in the backend group |
|
||||
| `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. |
|
||||
| `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. |
|
||||
| `traefik.backend.healthcheck.interval=1s` | Define the health check interval. |
|
||||
| `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm |
|
||||
| `traefik.backend.loadbalancer.stickiness=true` | Enable backend sticky sessions |
|
||||
| `traefik.backend.loadbalancer.stickiness.cookieName=NAME` | Manually set the cookie name for sticky sessions |
|
||||
| `traefik.backend.loadbalancer.sticky=true` | Enable backend sticky sessions (DEPRECATED) |
|
||||
| `traefik.backend.maxconn.amount=10` | Set a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect. |
|
||||
| `traefik.backend.maxconn.extractorfunc=client.ip` | Set the function to be used against the request to determine what to limit maximum connections to the backend by.<br>Must be used in conjunction with the above label to take effect. |
|
||||
| `traefik.backend.weight=10` | Assign this weight to the container |
|
||||
| `traefik.frontend.auth.basic=EXPR` | Sets basic authentication for that frontend in CSV format: `User:Hash,User:Hash` |
|
||||
| `traefik.frontend.entryPoints=http,https` | Assign this frontend to entry points `http` and `https`.<br>Overrides `defaultEntryPoints` |
|
||||
| `traefik.frontend.passHostHeader=true` | Forward client `Host` header to the backend. |
|
||||
| `traefik.frontend.passTLSCert=true` | Forward TLS Client certificates to the backend. |
|
||||
| `traefik.frontend.priority=10` | Override default frontend priority |
|
||||
| `traefik.frontend.redirect.entryPoint=https` | Enables Redirect to another entryPoint for that frontend (e.g. HTTPS) |
|
||||
| `traefik.frontend.redirect.regex=^http://localhost/(.*)` | Redirect to another URL for that frontend.<br>Must be set with `traefik.frontend.redirect.replacement`. |
|
||||
| `traefik.frontend.redirect.replacement=http://mydomain/$1` | Redirect to another URL for that frontend.<br>Must be set with `traefik.frontend.redirect.regex`. |
|
||||
| `traefik.frontend.redirect.permanent=true` | Return 301 instead of 302. |
|
||||
| `traefik.frontend.rule=EXPR` | Override the default frontend rule. Defaults to SF address. |
|
||||
| `traefik.frontend.whitelistSourceRange=RANGE` | List of IP-Ranges which are allowed to access.<br>An unset or empty list allows all Source-IPs to access.<br>If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. |
|
||||
|
||||
### Custom Headers
|
||||
|
||||
| Label | Description |
|
||||
|-------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `traefik.frontend.headers.customRequestHeaders=EXPR ` | Provides the container with custom request headers that will be appended to each request forwarded to the container.<br>Format: <code>HEADER:value||HEADER2:value2</code> |
|
||||
| `traefik.frontend.headers.customResponseHeaders=EXPR` | Appends the headers to each response returned by the container, before forwarding the response to the client.<br>Format: <code>HEADER:value||HEADER2:value2</code> |
|
||||
|
||||
### Security Headers
|
||||
|
||||
| Label | Description |
|
||||
|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `traefik.frontend.headers.allowedHosts=EXPR` | Provides a list of allowed hosts that requests will be processed.<br>Format: `Host1,Host2` |
|
||||
| `traefik.frontend.headers.hostsProxyHeaders=EXPR ` | Provides a list of headers that the proxied hostname may be stored.<br>Format: `HEADER1,HEADER2` |
|
||||
| `traefik.frontend.headers.SSLRedirect=true` | Forces the frontend to redirect to SSL if a non-SSL request is sent. |
|
||||
| `traefik.frontend.headers.SSLTemporaryRedirect=true` | Forces the frontend to redirect to SSL if a non-SSL request is sent, but by sending a 302 instead of a 301. |
|
||||
| `traefik.frontend.headers.SSLHost=HOST` | This setting configures the hostname that redirects will be based on. Default is "", which is the same host as the request. |
|
||||
| `traefik.frontend.headers.SSLProxyHeaders=EXPR` | Header combinations that would signify a proper SSL Request (Such as `X-Forwarded-For:https`).<br>Format: <code>HEADER:value||HEADER2:value2</code> |
|
||||
| `traefik.frontend.headers.STSSeconds=315360000` | Sets the max-age of the STS header. |
|
||||
| `traefik.frontend.headers.STSIncludeSubdomains=true` | Adds the `IncludeSubdomains` section of the STS header. |
|
||||
| `traefik.frontend.headers.STSPreload=true` | Adds the preload flag to the STS header. |
|
||||
| `traefik.frontend.headers.forceSTSHeader=false` | Adds the STS header to non-SSL requests. |
|
||||
| `traefik.frontend.headers.frameDeny=false` | Adds the `X-Frame-Options` header with the value of `DENY`. |
|
||||
| `traefik.frontend.headers.customFrameOptionsValue=VALUE` | Overrides the `X-Frame-Options` header with the custom value. |
|
||||
| `traefik.frontend.headers.contentTypeNosniff=true` | Adds the `X-Content-Type-Options` header with the value `nosniff`. |
|
||||
| `traefik.frontend.headers.browserXSSFilter=true` | Adds the X-XSS-Protection header with the value `1; mode=block`. |
|
||||
| `traefik.frontend.headers.customBrowserXSSValue=VALUE` | Set custom value for X-XSS-Protection header. This overrides the BrowserXssFilter option. |
|
||||
| `traefik.frontend.headers.contentSecurityPolicy=VALUE` | Adds CSP Header with the custom value. |
|
||||
| `traefik.frontend.headers.publicKey=VALUE` | Adds pinned HTST public key header. |
|
||||
| `traefik.frontend.headers.referrerPolicy=VALUE` | Adds referrer policy header. |
|
||||
| `traefik.frontend.headers.isDevelopment=false` | This will cause the `AllowedHosts`, `SSLRedirect`, and `STSSeconds`/`STSIncludeSubdomains` options to be ignored during development.<br>When deploying to production, be sure to set this to false. |
|
||||
|
|
59
vendor/github.com/containous/traefik-extra-service-fabric/labels.go
generated
vendored
59
vendor/github.com/containous/traefik-extra-service-fabric/labels.go
generated
vendored
|
@ -1,59 +0,0 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getFuncBoolLabel(labelName string, defaultValue bool) func(service ServiceItemExtended) bool {
|
||||
return func(service ServiceItemExtended) bool {
|
||||
return getBoolValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServiceStringLabel(service ServiceItemExtended, labelName string, defaultValue string) string {
|
||||
return getStringValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
|
||||
func hasFuncService(service ServiceItemExtended, labelName string) bool {
|
||||
return hasLabel(service.Labels, labelName)
|
||||
}
|
||||
|
||||
func getServiceLabelsWithPrefix(service ServiceItemExtended, prefix string) map[string]string {
|
||||
results := make(map[string]string)
|
||||
for k, v := range service.Labels {
|
||||
if strings.HasPrefix(k, prefix) {
|
||||
results[k] = v
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// must be replace by label.Has()
|
||||
// Deprecated
|
||||
func hasLabel(labels map[string]string, labelName string) bool {
|
||||
value, ok := labels[labelName]
|
||||
return ok && len(value) > 0
|
||||
}
|
||||
|
||||
// must be replace by label.GetStringValue()
|
||||
// Deprecated
|
||||
func getStringValue(labels map[string]string, labelName string, defaultValue string) string {
|
||||
if value, ok := labels[labelName]; ok && len(value) > 0 {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// must be replace by label.GetBoolValue()
|
||||
// Deprecated
|
||||
func getBoolValue(labels map[string]string, labelName string, defaultValue bool) bool {
|
||||
rawValue, ok := labels[labelName]
|
||||
if ok {
|
||||
v, err := strconv.ParseBool(rawValue)
|
||||
if err == nil {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
165
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric.go
generated
vendored
165
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric.go
generated
vendored
|
@ -1,17 +1,14 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/cenk/backoff"
|
||||
"github.com/containous/traefik/job"
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/provider"
|
||||
"github.com/containous/traefik/provider/label"
|
||||
"github.com/containous/traefik/safe"
|
||||
"github.com/containous/traefik/types"
|
||||
sf "github.com/jjcollinge/servicefabric"
|
||||
|
@ -19,7 +16,7 @@ import (
|
|||
|
||||
var _ provider.Provider = (*Provider)(nil)
|
||||
|
||||
const traefikLabelPrefix = "traefik"
|
||||
const traefikServiceFabricExtensionKey = "Traefik"
|
||||
|
||||
// Provider holds for configuration for the provider
|
||||
type Provider struct {
|
||||
|
@ -93,104 +90,6 @@ func (p *Provider) updateConfig(configurationChan chan<- types.ConfigMessage, po
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) buildConfiguration(sfClient sfClient) (*types.Configuration, error) {
|
||||
var sfFuncMap = template.FuncMap{
|
||||
"getServices": getServices,
|
||||
"hasLabel": hasFuncService,
|
||||
"getLabelValue": getFuncServiceStringLabel,
|
||||
"getLabelsWithPrefix": getServiceLabelsWithPrefix,
|
||||
"isPrimary": isPrimary,
|
||||
"isExposed": getFuncBoolLabel("expose", false),
|
||||
"getBackendName": getBackendName,
|
||||
"getDefaultEndpoint": getDefaultEndpoint,
|
||||
"getNamedEndpoint": getNamedEndpoint, // FIXME unused
|
||||
"getApplicationParameter": getApplicationParameter, // FIXME unused
|
||||
"doesAppParamContain": doesAppParamContain, // FIXME unused
|
||||
"filterServicesByLabelValue": filterServicesByLabelValue, // FIXME unused
|
||||
}
|
||||
|
||||
services, err := getClusterServices(sfClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
templateObjects := struct {
|
||||
Services []ServiceItemExtended
|
||||
}{
|
||||
Services: services,
|
||||
}
|
||||
|
||||
return p.GetConfiguration(tmpl, sfFuncMap, templateObjects)
|
||||
}
|
||||
|
||||
func getDefaultEndpoint(instance replicaInstance) string {
|
||||
id, data := instance.GetReplicaData()
|
||||
endpoint, err := getReplicaDefaultEndpoint(data)
|
||||
if err != nil {
|
||||
log.Warnf("No default endpoint for replica %s in service %s endpointData: %s", id, data.Address)
|
||||
return ""
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func getReplicaDefaultEndpoint(replicaData *sf.ReplicaItemBase) (string, error) {
|
||||
endpoints, err := decodeEndpointData(replicaData.Address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var defaultHTTPEndpoint string
|
||||
for _, v := range endpoints {
|
||||
if strings.Contains(v, "http") {
|
||||
defaultHTTPEndpoint = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(defaultHTTPEndpoint) == 0 {
|
||||
return "", errors.New("no default endpoint found")
|
||||
}
|
||||
return defaultHTTPEndpoint, nil
|
||||
}
|
||||
|
||||
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 doesAppParamContain(app sf.ApplicationItem, key, shouldContain string) bool {
|
||||
value := getApplicationParameter(app, key)
|
||||
return strings.Contains(value, shouldContain)
|
||||
}
|
||||
|
||||
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 getClusterServices(sfClient sfClient) ([]ServiceItemExtended, error) {
|
||||
apps, err := sfClient.GetApplications()
|
||||
if err != nil {
|
||||
|
@ -210,7 +109,7 @@ func getClusterServices(sfClient sfClient) ([]ServiceItemExtended, error) {
|
|||
Application: app,
|
||||
}
|
||||
|
||||
if labels, err := sfClient.GetServiceLabels(&service, &app, traefikLabelPrefix); err != nil {
|
||||
if labels, err := getLabels(sfClient, &service, &app); err != nil {
|
||||
log.Error(err)
|
||||
} else {
|
||||
item.Labels = labels
|
||||
|
@ -222,9 +121,9 @@ func getClusterServices(sfClient sfClient) ([]ServiceItemExtended, error) {
|
|||
for _, partition := range partitions.Items {
|
||||
partitionExt := PartitionItemExtended{PartitionItem: partition}
|
||||
|
||||
if partition.ServiceKind == "Stateful" {
|
||||
if isStateful(item) {
|
||||
partitionExt.Replicas = getValidReplicas(sfClient, app, service, partition)
|
||||
} else if partition.ServiceKind == "Stateless" {
|
||||
} else if isStateless(item) {
|
||||
partitionExt.Instances = getValidInstances(sfClient, app, service, partition)
|
||||
} else {
|
||||
log.Errorf("Unsupported service kind %s in service %s", partition.ServiceKind, service.Name)
|
||||
|
@ -272,31 +171,6 @@ func getValidInstances(sfClient sfClient, app sf.ApplicationItem, service sf.Ser
|
|||
return validInstances
|
||||
}
|
||||
|
||||
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 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 isPrimary(instance replicaInstance) bool {
|
||||
_, data := instance.GetReplicaData()
|
||||
return data.ReplicaRole == "Primary"
|
||||
|
@ -311,26 +185,21 @@ func hasHTTPEndpoint(instanceData *sf.ReplicaItemBase) bool {
|
|||
return err == nil
|
||||
}
|
||||
|
||||
func decodeEndpointData(endpointData string) (map[string]string, error) {
|
||||
var endpointsMap map[string]map[string]string
|
||||
|
||||
if endpointData == "" {
|
||||
return nil, errors.New("endpoint data is empty")
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(endpointData), &endpointsMap)
|
||||
// Return a set of labels from the Extension and Property manager
|
||||
// Allow Extension labels to disable importing labels from the property manager.
|
||||
func getLabels(sfClient sfClient, service *sf.ServiceItem, app *sf.ApplicationItem) (map[string]string, error) {
|
||||
labels, err := sfClient.GetServiceExtensionMap(service, app, traefikServiceFabricExtensionKey)
|
||||
if err != nil {
|
||||
log.Errorf("Error retrieving serviceExtensionMap: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpoints, endpointsExist := endpointsMap["Endpoints"]
|
||||
if !endpointsExist {
|
||||
return nil, errors.New("endpoint doesn't exist in endpoint data")
|
||||
if label.GetBoolValue(labels, traefikSFEnableLabelOverrides, traefikSFEnableLabelOverridesDefault) {
|
||||
if exists, properties, err := sfClient.GetProperties(service.ID); err == nil && exists {
|
||||
for key, value := range properties {
|
||||
labels[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
func getBackendName(service ServiceItemExtended, partition PartitionItemExtended) string {
|
||||
return provider.Normalize(service.Name + partition.PartitionInformation.ID)
|
||||
return labels, nil
|
||||
}
|
||||
|
|
321
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_config.go
generated
vendored
Normal file
321
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_config.go
generated
vendored
Normal file
|
@ -0,0 +1,321 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
"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"
|
||||
)
|
||||
|
||||
func (p *Provider) buildConfiguration(sfClient sfClient) (*types.Configuration, error) {
|
||||
var sfFuncMap = template.FuncMap{
|
||||
|
||||
// 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
|
||||
"getWeight": getFuncServiceStringLabel(label.TraefikWeight, label.DefaultWeight),
|
||||
"getProtocol": getFuncServiceStringLabel(label.TraefikProtocol, label.DefaultProtocol),
|
||||
"getMaxConn": getMaxConn,
|
||||
"getHealthCheck": getHealthCheck,
|
||||
"getCircuitBreaker": getCircuitBreaker,
|
||||
"getLoadBalancer": getLoadBalancer,
|
||||
|
||||
// Frontend Functions
|
||||
"getPriority": getFuncServiceStringLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
|
||||
"getPassHostHeader": getFuncServiceStringLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeader),
|
||||
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, false),
|
||||
"getEntryPoints": getFuncServiceSliceStringLabel(label.TraefikFrontendEntryPoints),
|
||||
"getBasicAuth": getFuncServiceSliceStringLabel(label.TraefikFrontendAuthBasic),
|
||||
"getWhitelistSourceRange": getFuncServiceSliceStringLabel(label.TraefikFrontendWhitelistSourceRange),
|
||||
"getFrontendRules": getFuncServiceLabelWithPrefix(label.TraefikFrontendRule),
|
||||
|
||||
"getHeaders": getHeaders,
|
||||
"getRedirect": getRedirect,
|
||||
|
||||
// SF Service Grouping
|
||||
"getGroupedServices": getFuncServicesGroupedByLabel(traefikSFGroupName),
|
||||
"getGroupedWeight": getFuncServiceStringLabel(traefikSFGroupWeight, "1"),
|
||||
}
|
||||
|
||||
services, err := getClusterServices(sfClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
templateObjects := struct {
|
||||
Services []ServiceItemExtended
|
||||
}{
|
||||
Services: services,
|
||||
}
|
||||
|
||||
return p.GetConfiguration(tmpl, sfFuncMap, templateObjects)
|
||||
}
|
||||
|
||||
func isStateful(service ServiceItemExtended) bool {
|
||||
return service.ServiceKind == "Stateful"
|
||||
}
|
||||
|
||||
func isStateless(service ServiceItemExtended) bool {
|
||||
return service.ServiceKind == "Stateless"
|
||||
}
|
||||
|
||||
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 {
|
||||
log.Warnf("No default endpoint for replica %s in service %s endpointData: %s", id, data.Address)
|
||||
return ""
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func getReplicaDefaultEndpoint(replicaData *sf.ReplicaItemBase) (string, error) {
|
||||
endpoints, err := decodeEndpointData(replicaData.Address)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var defaultHTTPEndpoint string
|
||||
for _, v := range endpoints {
|
||||
if strings.Contains(v, "http") {
|
||||
defaultHTTPEndpoint = v
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(defaultHTTPEndpoint) == 0 {
|
||||
return "", errors.New("no default endpoint found")
|
||||
}
|
||||
return defaultHTTPEndpoint, nil
|
||||
}
|
||||
|
||||
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 decodeEndpointData(endpointData string) (map[string]string, error) {
|
||||
var endpointsMap map[string]map[string]string
|
||||
|
||||
if endpointData == "" {
|
||||
return nil, errors.New("endpoint data is empty")
|
||||
}
|
||||
|
||||
err := json.Unmarshal([]byte(endpointData), &endpointsMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpoints, endpointsExist := endpointsMap["Endpoints"]
|
||||
if !endpointsExist {
|
||||
return nil, errors.New("endpoint doesn't exist in endpoint data")
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
func getHeaders(service ServiceItemExtended) *types.Headers {
|
||||
headers := &types.Headers{
|
||||
CustomRequestHeaders: label.GetMapValue(service.Labels, label.TraefikFrontendRequestHeaders),
|
||||
CustomResponseHeaders: label.GetMapValue(service.Labels, label.TraefikFrontendResponseHeaders),
|
||||
SSLProxyHeaders: label.GetMapValue(service.Labels, label.TraefikFrontendSSLProxyHeaders),
|
||||
AllowedHosts: label.GetSliceStringValue(service.Labels, label.TraefikFrontendAllowedHosts),
|
||||
HostsProxyHeaders: label.GetSliceStringValue(service.Labels, label.TraefikFrontendHostsProxyHeaders),
|
||||
STSSeconds: label.GetInt64Value(service.Labels, label.TraefikFrontendSTSSeconds, 0),
|
||||
SSLRedirect: label.GetBoolValue(service.Labels, label.TraefikFrontendSSLRedirect, false),
|
||||
SSLTemporaryRedirect: label.GetBoolValue(service.Labels, label.TraefikFrontendSSLTemporaryRedirect, false),
|
||||
STSIncludeSubdomains: label.GetBoolValue(service.Labels, label.TraefikFrontendSTSIncludeSubdomains, false),
|
||||
STSPreload: label.GetBoolValue(service.Labels, label.TraefikFrontendSTSPreload, false),
|
||||
ForceSTSHeader: label.GetBoolValue(service.Labels, label.TraefikFrontendForceSTSHeader, false),
|
||||
FrameDeny: label.GetBoolValue(service.Labels, label.TraefikFrontendFrameDeny, false),
|
||||
ContentTypeNosniff: label.GetBoolValue(service.Labels, label.TraefikFrontendContentTypeNosniff, false),
|
||||
BrowserXSSFilter: label.GetBoolValue(service.Labels, label.TraefikFrontendBrowserXSSFilter, false),
|
||||
IsDevelopment: label.GetBoolValue(service.Labels, label.TraefikFrontendIsDevelopment, false),
|
||||
SSLHost: label.GetStringValue(service.Labels, label.TraefikFrontendSSLHost, ""),
|
||||
CustomFrameOptionsValue: label.GetStringValue(service.Labels, label.TraefikFrontendCustomFrameOptionsValue, ""),
|
||||
ContentSecurityPolicy: label.GetStringValue(service.Labels, label.TraefikFrontendContentSecurityPolicy, ""),
|
||||
PublicKey: label.GetStringValue(service.Labels, label.TraefikFrontendPublicKey, ""),
|
||||
ReferrerPolicy: label.GetStringValue(service.Labels, label.TraefikFrontendReferrerPolicy, ""),
|
||||
CustomBrowserXSSValue: label.GetStringValue(service.Labels, label.TraefikFrontendCustomBrowserXSSValue, ""),
|
||||
}
|
||||
|
||||
if !headers.HasSecureHeadersDefined() && !headers.HasCustomHeadersDefined() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
func getRedirect(service ServiceItemExtended) *types.Redirect {
|
||||
permanent := label.GetBoolValue(service.Labels, label.TraefikFrontendRedirectPermanent, false)
|
||||
|
||||
if label.Has(service.Labels, label.TraefikFrontendRedirectEntryPoint) {
|
||||
return &types.Redirect{
|
||||
EntryPoint: label.GetStringValue(service.Labels, label.TraefikFrontendRedirectEntryPoint, ""),
|
||||
Permanent: permanent,
|
||||
}
|
||||
}
|
||||
|
||||
if label.Has(service.Labels, label.TraefikFrontendRedirectRegex) &&
|
||||
label.Has(service.Labels, label.TraefikFrontendRedirectReplacement) {
|
||||
return &types.Redirect{
|
||||
Regex: label.GetStringValue(service.Labels, label.TraefikFrontendRedirectRegex, ""),
|
||||
Replacement: label.GetStringValue(service.Labels, label.TraefikFrontendRedirectReplacement, ""),
|
||||
Permanent: permanent,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMaxConn(service ServiceItemExtended) *types.MaxConn {
|
||||
amount := label.GetInt64Value(service.Labels, label.TraefikBackendMaxConnAmount, math.MinInt64)
|
||||
extractorFunc := label.GetStringValue(service.Labels, label.TraefikBackendMaxConnExtractorFunc, label.DefaultBackendMaxconnExtractorFunc)
|
||||
|
||||
if amount == math.MinInt64 || len(extractorFunc) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &types.MaxConn{
|
||||
Amount: amount,
|
||||
ExtractorFunc: extractorFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func getHealthCheck(service ServiceItemExtended) *types.HealthCheck {
|
||||
path := label.GetStringValue(service.Labels, label.TraefikBackendHealthCheckPath, "")
|
||||
if len(path) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
port := label.GetIntValue(service.Labels, label.TraefikBackendHealthCheckPort, label.DefaultBackendHealthCheckPort)
|
||||
interval := label.GetStringValue(service.Labels, label.TraefikBackendHealthCheckInterval, "")
|
||||
|
||||
return &types.HealthCheck{
|
||||
Path: path,
|
||||
Port: port,
|
||||
Interval: interval,
|
||||
}
|
||||
}
|
||||
|
||||
func getCircuitBreaker(service ServiceItemExtended) *types.CircuitBreaker {
|
||||
circuitBreaker := label.GetStringValue(service.Labels, label.TraefikBackendCircuitBreakerExpression, "")
|
||||
if len(circuitBreaker) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &types.CircuitBreaker{Expression: circuitBreaker}
|
||||
}
|
||||
|
||||
func getLoadBalancer(service ServiceItemExtended) *types.LoadBalancer {
|
||||
if !label.HasPrefix(service.Labels, label.TraefikBackendLoadBalancer) {
|
||||
return nil
|
||||
}
|
||||
|
||||
method := label.GetStringValue(service.Labels, label.TraefikBackendLoadBalancerMethod, label.DefaultBackendLoadBalancerMethod)
|
||||
|
||||
lb := &types.LoadBalancer{
|
||||
Method: method,
|
||||
Sticky: getSticky(service),
|
||||
}
|
||||
|
||||
if label.GetBoolValue(service.Labels, label.TraefikBackendLoadBalancerStickiness, false) {
|
||||
cookieName := label.GetStringValue(service.Labels, label.TraefikBackendLoadBalancerStickinessCookieName, label.DefaultBackendLoadbalancerStickinessCookieName)
|
||||
lb.Stickiness = &types.Stickiness{CookieName: cookieName}
|
||||
}
|
||||
|
||||
return lb
|
||||
}
|
||||
|
||||
// TODO: Deprecated
|
||||
// replaced by Stickiness
|
||||
// Deprecated
|
||||
func getSticky(service ServiceItemExtended) bool {
|
||||
if label.Has(service.Labels, label.TraefikBackendLoadBalancerSticky) {
|
||||
log.Warnf("Deprecated configuration found: %s. Please use %s.", label.TraefikBackendLoadBalancerSticky, label.TraefikBackendLoadBalancerStickiness)
|
||||
}
|
||||
|
||||
return label.GetBoolValue(service.Labels, label.TraefikBackendLoadBalancerSticky, false)
|
||||
}
|
63
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_labelfuncs.go
generated
vendored
Normal file
63
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_labelfuncs.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
package servicefabric
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/containous/traefik/provider/label"
|
||||
)
|
||||
|
||||
// SF Specific Traefik Labels
|
||||
const (
|
||||
traefikSFGroupName = "traefik.servicefabric.groupname"
|
||||
traefikSFGroupWeight = "traefik.servicefabric.groupweight"
|
||||
traefikSFEnableLabelOverrides = "traefik.servicefabric.enablelabeloverrides"
|
||||
traefikSFEnableLabelOverridesDefault = true
|
||||
)
|
||||
|
||||
func getFuncBoolLabel(labelName string, defaultValue bool) func(service ServiceItemExtended) bool {
|
||||
return func(service ServiceItemExtended) bool {
|
||||
return label.GetBoolValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getServiceStringLabel(service ServiceItemExtended, labelName string, defaultValue string) string {
|
||||
return label.GetStringValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
|
||||
func getFuncServiceStringLabel(labelName string, defaultValue string) func(service ServiceItemExtended) string {
|
||||
return func(service ServiceItemExtended) string {
|
||||
return label.GetStringValue(service.Labels, labelName, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServiceSliceStringLabel(labelName string) func(service ServiceItemExtended) []string {
|
||||
return func(service ServiceItemExtended) []string {
|
||||
return label.GetSliceStringValue(service.Labels, labelName)
|
||||
}
|
||||
}
|
||||
|
||||
func hasService(service ServiceItemExtended, labelName string) bool {
|
||||
return label.Has(service.Labels, labelName)
|
||||
}
|
||||
|
||||
func getFuncServiceLabelWithPrefix(labelName string) func(service ServiceItemExtended) map[string]string {
|
||||
return func(service ServiceItemExtended) map[string]string {
|
||||
return getServiceLabelsWithPrefix(service, labelName)
|
||||
}
|
||||
}
|
||||
|
||||
func getFuncServicesGroupedByLabel(labelName string) func(services []ServiceItemExtended) map[string][]ServiceItemExtended {
|
||||
return func(services []ServiceItemExtended) map[string][]ServiceItemExtended {
|
||||
return getServices(services, labelName)
|
||||
}
|
||||
}
|
||||
|
||||
func getServiceLabelsWithPrefix(service ServiceItemExtended, prefix string) map[string]string {
|
||||
results := make(map[string]string)
|
||||
for k, v := range service.Labels {
|
||||
if strings.HasPrefix(k, prefix) {
|
||||
results[k] = v
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
293
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_tmpl.go
generated
vendored
293
vendor/github.com/containous/traefik-extra-service-fabric/servicefabric_tmpl.go
generated
vendored
|
@ -1,140 +1,209 @@
|
|||
package servicefabric
|
||||
|
||||
const tmpl = `
|
||||
{{$groupedServiceMap := getServices .Services "backend.group.name"}}
|
||||
[backends]
|
||||
{{range $aggName, $aggServices := $groupedServiceMap }}
|
||||
[backends."{{$aggName}}"]
|
||||
{{range $service := $aggServices}}
|
||||
{{range $partition := $service.Partitions}}
|
||||
{{range $instance := $partition.Instances}}
|
||||
[backends."{{$aggName}}".servers."{{$service.ID}}-{{$instance.ID}}"]
|
||||
url = "{{getDefaultEndpoint $instance}}"
|
||||
weight = {{getLabelValue $service "backend.group.weight" "1"}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{range $service := .Services}}
|
||||
{{range $partition := $service.Partitions}}
|
||||
{{if eq $partition.ServiceKind "Stateless"}}
|
||||
[backends."{{$service.Name}}"]
|
||||
[backends."{{$service.Name}}".LoadBalancer]
|
||||
{{if hasLabel $service "backend.loadbalancer.method"}}
|
||||
method = "{{getLabelValue $service "backend.loadbalancer.method" "" }}"
|
||||
{{else}}
|
||||
method = "drr"
|
||||
{{range $aggName, $aggServices := getGroupedServices .Services }}
|
||||
[backends."{{ $aggName }}"]
|
||||
{{range $service := $aggServices }}
|
||||
{{range $partition := $service.Partitions }}
|
||||
{{range $instance := $partition.Instances }}
|
||||
[backends."{{ $aggName }}".servers."{{ $service.ID }}-{{ $instance.ID }}"]
|
||||
url = "{{ getDefaultEndpoint $instance }}"
|
||||
weight = {{ getGroupedWeight $service }}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $service := .Services }}
|
||||
{{if isEnabled $service }}
|
||||
{{range $partition := $service.Partitions }}
|
||||
|
||||
{{if isStateless $service }}
|
||||
|
||||
{{ $backendName := $service.Name }}
|
||||
[backends."{{ $backendName }}"]
|
||||
|
||||
{{ $circuitBreaker := getCircuitBreaker $service }}
|
||||
{{if $circuitBreaker }}
|
||||
[backends."{{ $backendName }}".circuitBreaker]
|
||||
expression = "{{ $circuitBreaker.Expression }}"
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "backend.healthcheck"}}
|
||||
[backends."{{$service.Name}}".healthcheck]
|
||||
path = "{{getLabelValue $service "backend.healthcheck" ""}}"
|
||||
interval = "{{getLabelValue $service "backend.healthcheck.interval" "10s"}}"
|
||||
{{ $loadBalancer := getLoadBalancer $service }}
|
||||
{{if $loadBalancer }}
|
||||
[backends."{{ $backendName }}".loadBalancer]
|
||||
method = "{{ $loadBalancer.Method }}"
|
||||
sticky = {{ $loadBalancer.Sticky }}
|
||||
{{if $loadBalancer.Stickiness }}
|
||||
[backends."{{ $backendName }}".loadBalancer.stickiness]
|
||||
cookieName = "{{ $loadBalancer.Stickiness.CookieName }}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "backend.loadbalancer.stickiness"}}
|
||||
[backends."{{$service.Name}}".LoadBalancer.stickiness]
|
||||
{{ $maxConn := getMaxConn $service }}
|
||||
{{if $maxConn }}
|
||||
[backends."{{ $backendName }}".maxConn]
|
||||
extractorFunc = "{{ $maxConn.ExtractorFunc }}"
|
||||
amount = {{ $maxConn.Amount }}
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "backend.circuitbreaker"}}
|
||||
[backends."{{$service.Name}}".circuitbreaker]
|
||||
expression = "{{getLabelValue $service "backend.circuitbreaker" ""}}"
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "backend.maxconn.amount"}}
|
||||
[backends."{{$service.Name}}".maxconn]
|
||||
amount = {{getLabelValue $service "backend.maxconn.amount" ""}}
|
||||
{{if hasLabel $service "backend.maxconn.extractorfunc"}}
|
||||
extractorfunc = "{{getLabelValue $service "backend.maxconn.extractorfunc" ""}}"
|
||||
{{end}}
|
||||
{{ $healthCheck := getHealthCheck $service }}
|
||||
{{if $healthCheck }}
|
||||
[backends."{{ $backendName }}".healthCheck]
|
||||
path = "{{ $healthCheck.Path }}"
|
||||
port = {{ $healthCheck.Port }}
|
||||
interval = "{{ $healthCheck.Interval }}"
|
||||
{{end}}
|
||||
|
||||
{{range $instance := $partition.Instances}}
|
||||
[backends."{{$service.Name}}".servers."{{$instance.ID}}"]
|
||||
url = "{{getDefaultEndpoint $instance}}"
|
||||
weight = {{getLabelValue $service "backend.weight" "1"}}
|
||||
[backends."{{ $service.Name }}".servers."{{ $instance.ID }}"]
|
||||
url = "{{ getDefaultEndpoint $instance }}"
|
||||
weight = {{ getLabelValue $service "backend.weight" "1" }}
|
||||
{{end}}
|
||||
{{else if eq $partition.ServiceKind "Stateful"}}
|
||||
|
||||
{{else if isStateful $service}}
|
||||
|
||||
{{range $replica := $partition.Replicas}}
|
||||
{{if isPrimary $replica}}
|
||||
|
||||
{{$backendName := getBackendName $service.Name $partition}}
|
||||
[backends."{{$backendName}}".servers."{{$replica.ID}}"]
|
||||
url = "{{getDefaultEndpoint $replica}}"
|
||||
weight = 1
|
||||
{{ $backendName := getBackendName $service $partition }}
|
||||
[backends."{{ $backendName }}".servers."{{ $replica.ID }}"]
|
||||
url = "{{ getDefaultEndpoint $replica }}"
|
||||
weight = 1
|
||||
|
||||
[backends."{{$backendName}}".LoadBalancer]
|
||||
method = "drr"
|
||||
|
||||
[backends."{{$backendName}}".circuitbreaker]
|
||||
expression = "NetworkErrorRatio() > 0.5"
|
||||
method = "drr"
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
[frontends]
|
||||
{{range $groupName, $groupServices := $groupedServiceMap}}
|
||||
{{$service := index $groupServices 0}}
|
||||
[frontends."{{$groupName}}"]
|
||||
backend = "{{$groupName}}"
|
||||
|
||||
{{if hasLabel $service "frontend.priority"}}
|
||||
priority = 100
|
||||
{{end}}
|
||||
|
||||
{{range $key, $value := getLabelsWithPrefix $service "frontend.rule"}}
|
||||
[frontends."{{$groupName}}".routes."{{$key}}"]
|
||||
rule = "{{$value}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{range $service := .Services}}
|
||||
{{if isExposed $service}}
|
||||
{{if eq $service.ServiceKind "Stateless"}}
|
||||
|
||||
[frontends."{{$service.Name}}"]
|
||||
backend = "{{$service.Name}}"
|
||||
|
||||
{{if hasLabel $service "frontend.passHostHeader"}}
|
||||
passHostHeader = {{getLabelValue $service "frontend.passHostHeader" ""}}
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "frontend.whitelistSourceRange"}}
|
||||
whitelistSourceRange = {{getLabelValue $service "frontend.whitelistSourceRange" ""}}
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "frontend.priority"}}
|
||||
priority = {{getLabelValue $service "frontend.priority" ""}}
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "frontend.basicAuth"}}
|
||||
basicAuth = {{getLabelValue $service "frontend.basicAuth" ""}}
|
||||
{{end}}
|
||||
|
||||
{{if hasLabel $service "frontend.entryPoints"}}
|
||||
entryPoints = {{getLabelValue $service "frontend.entryPoints" ""}}
|
||||
{{end}}
|
||||
|
||||
{{range $key, $value := getLabelsWithPrefix $service "frontend.rule"}}
|
||||
[frontends."{{$service.Name}}".routes."{{$key}}"]
|
||||
rule = "{{$value}}"
|
||||
{{end}}
|
||||
|
||||
{{else if eq $service.ServiceKind "Stateful"}}
|
||||
{{range $partition := $service.Partitions}}
|
||||
{{$partitionId := $partition.PartitionInformation.ID}}
|
||||
|
||||
{{if hasLabel $service "frontend.rule"}}
|
||||
[frontends."{{$service.Name}}/{{$partitionId}}"]
|
||||
backend = "{{getBackendName $service.Name $partition}}"
|
||||
[frontends."{{$service.Name}}/{{$partitionId}}".routes.default]
|
||||
rule = {{getLabelValue $service "frontend.rule.partition.$partitionId" ""}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
[frontends]
|
||||
{{range $groupName, $groupServices := getGroupedServices .Services }}
|
||||
{{ $service := index $groupServices 0 }}
|
||||
[frontends."{{ $groupName }}"]
|
||||
backend = "{{ $groupName }}"
|
||||
priority = 50
|
||||
|
||||
{{range $key, $value := getFrontendRules $service }}
|
||||
[frontends."{{ $groupName }}".routes."{{ $key }}"]
|
||||
rule = "{{ $value }}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $service := .Services }}
|
||||
{{if isEnabled $service }}
|
||||
{{ $frontendName := $service.Name }}
|
||||
|
||||
{{if isStateless $service }}
|
||||
|
||||
[frontends."frontend-{{ $frontendName }}"]
|
||||
backend = "{{ $service.Name }}"
|
||||
passHostHeader = {{ getPassHostHeader $service }}
|
||||
passTLSCert = {{ getPassTLSCert $service }}
|
||||
priority = {{ getPriority $service }}
|
||||
|
||||
{{ $entryPoints := getEntryPoints $service }}
|
||||
{{if $entryPoints }}
|
||||
entryPoints = [{{range $entryPoints }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ $whitelistSourceRange := getWhitelistSourceRange $service }}
|
||||
{{if $whitelistSourceRange }}
|
||||
whitelistSourceRange = [{{range $whitelistSourceRange }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ $basicAuth := getBasicAuth $service }}
|
||||
{{if $basicAuth }}
|
||||
basicAuth = [{{range $basicAuth }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{ $headers := getHeaders $service }}
|
||||
{{if $headers }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers]
|
||||
SSLRedirect = {{ $headers.SSLRedirect }}
|
||||
SSLTemporaryRedirect = {{ $headers.SSLTemporaryRedirect }}
|
||||
SSLHost = "{{ $headers.SSLHost }}"
|
||||
STSSeconds = {{ $headers.STSSeconds }}
|
||||
STSIncludeSubdomains = {{ $headers.STSIncludeSubdomains }}
|
||||
STSPreload = {{ $headers.STSPreload }}
|
||||
ForceSTSHeader = {{ $headers.ForceSTSHeader }}
|
||||
FrameDeny = {{ $headers.FrameDeny }}
|
||||
CustomFrameOptionsValue = "{{ $headers.CustomFrameOptionsValue }}"
|
||||
ContentTypeNosniff = {{ $headers.ContentTypeNosniff }}
|
||||
BrowserXSSFilter = {{ $headers.BrowserXSSFilter }}
|
||||
CustomBrowserXSSValue = "{{ $headers.CustomBrowserXSSValue }}"
|
||||
ContentSecurityPolicy = "{{ $headers.ContentSecurityPolicy }}"
|
||||
PublicKey = "{{ $headers.PublicKey }}"
|
||||
ReferrerPolicy = "{{ $headers.ReferrerPolicy }}"
|
||||
IsDevelopment = {{ $headers.IsDevelopment }}
|
||||
|
||||
{{if $headers.AllowedHosts }}
|
||||
AllowedHosts = [{{range $headers.AllowedHosts }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{if $headers.HostsProxyHeaders }}
|
||||
HostsProxyHeaders = [{{range $headers.HostsProxyHeaders }}
|
||||
"{{.}}",
|
||||
{{end}}]
|
||||
{{end}}
|
||||
|
||||
{{if $headers.CustomRequestHeaders }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers.customRequestHeaders]
|
||||
{{range $k, $v := $headers.CustomRequestHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if $headers.CustomResponseHeaders }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers.customResponseHeaders]
|
||||
{{range $k, $v := $headers.CustomResponseHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if $headers.SSLProxyHeaders }}
|
||||
[frontends."frontend-{{ $frontendName }}".headers.SSLProxyHeaders]
|
||||
{{range $k, $v := $headers.SSLProxyHeaders }}
|
||||
{{$k}} = "{{$v}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{range $key, $value := getFrontendRules $service }}
|
||||
[frontends."frontend-{{ $frontendName }}".routes."{{ $key }}"]
|
||||
rule = "{{ $value }}"
|
||||
{{end}}
|
||||
|
||||
{{else if isStateful $service}}
|
||||
|
||||
{{range $partition := $service.Partitions }}
|
||||
{{ $partitionId := $partition.PartitionInformation.ID }}
|
||||
|
||||
{{if hasLabel $service "frontend.rule" }}
|
||||
[frontends."{{ $service.Name }}/{{ $partitionId }}"]
|
||||
backend = "{{ getBackendName $service.Name $partition }}"
|
||||
|
||||
[frontends."{{ $service.Name }}/{{ $partitionId }}".routes.default]
|
||||
rule = {{ getLabelValue $service "frontend.rule.partition.$partitionId" "" }}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
`
|
||||
|
|
11
vendor/github.com/containous/traefik-extra-service-fabric/types.go
generated
vendored
11
vendor/github.com/containous/traefik-extra-service-fabric/types.go
generated
vendored
|
@ -9,11 +9,9 @@ import (
|
|||
// it belongs too and the replicas/partitions
|
||||
type ServiceItemExtended struct {
|
||||
sf.ServiceItem
|
||||
HasHTTPEndpoint bool
|
||||
IsHealthy bool
|
||||
Application sf.ApplicationItem
|
||||
Partitions []PartitionItemExtended
|
||||
Labels map[string]string
|
||||
Application sf.ApplicationItem
|
||||
Partitions []PartitionItemExtended
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// PartitionItemExtended provides a flattened view
|
||||
|
@ -32,8 +30,9 @@ type sfClient interface {
|
|||
GetPartitions(appName, serviceName string) (*sf.PartitionItemsPage, error)
|
||||
GetReplicas(appName, serviceName, partitionName string) (*sf.ReplicaItemsPage, error)
|
||||
GetInstances(appName, serviceName, partitionName string) (*sf.InstanceItemsPage, error)
|
||||
GetServiceExtension(appType, applicationVersion, serviceTypeName, extensionKey string, response interface{}) error
|
||||
GetServiceExtensionMap(service *sf.ServiceItem, app *sf.ApplicationItem, extensionKey string) (map[string]string, error)
|
||||
GetServiceLabels(service *sf.ServiceItem, app *sf.ApplicationItem, prefix string) (map[string]string, error)
|
||||
GetProperties(name string) (bool, map[string]string, error)
|
||||
}
|
||||
|
||||
// replicaInstance interface provides a unified interface
|
||||
|
|
24
vendor/github.com/jjcollinge/servicefabric/servicefabric.go
generated
vendored
24
vendor/github.com/jjcollinge/servicefabric/servicefabric.go
generated
vendored
|
@ -219,8 +219,30 @@ func (c Client) GetServiceExtension(appType, applicationVersion, serviceTypeName
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetServiceExtensionMap returns all the extension xml specified
|
||||
// in a Service's manifest file into (which must conform to ServiceExtensionLabels)
|
||||
// a map[string]string
|
||||
func (c Client) GetServiceExtensionMap(service *ServiceItem, app *ApplicationItem, extensionKey string) (map[string]string, error) {
|
||||
extensionData := ServiceExtensionLabels{}
|
||||
err := c.GetServiceExtension(app.TypeName, app.TypeVersion, service.TypeName, extensionKey, &extensionData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labels := map[string]string{}
|
||||
if extensionData.Label != nil {
|
||||
for _, label := range extensionData.Label {
|
||||
labels[label.Key] = label.Value
|
||||
}
|
||||
}
|
||||
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
// GetProperties uses the Property Manager API to retrieve
|
||||
// string properties from a name as a dictionary
|
||||
// Property name is the path to the properties you would like to list.
|
||||
// for example a serviceID
|
||||
func (c Client) GetProperties(name string) (bool, map[string]string, error) {
|
||||
nameExists, err := c.nameExists(name)
|
||||
if err != nil {
|
||||
|
@ -264,6 +286,8 @@ func (c Client) GetProperties(name string) (bool, map[string]string, error) {
|
|||
|
||||
// GetServiceLabels add labels from service manifest extensions and properties manager
|
||||
// expects extension xml in <Label key="key">value</Label>
|
||||
//
|
||||
// Deprecated: Use GetProperties and GetServiceExtensionMap instead.
|
||||
func (c Client) GetServiceLabels(service *ServiceItem, app *ApplicationItem, prefix string) (map[string]string, error) {
|
||||
extensionData := ServiceExtensionLabels{}
|
||||
err := c.GetServiceExtension(app.TypeName, app.TypeVersion, service.TypeName, prefix, &extensionData)
|
||||
|
|
Loading…
Reference in a new issue