Merge branch 'v3.0' of github.com:traefik/traefik

This commit is contained in:
baalajimaestro 2022-12-21 16:42:57 +05:30
commit 3fcde5aded
Signed by: baalajimaestro
GPG key ID: F93C394FE9BBAFD5
107 changed files with 1044 additions and 12876 deletions

View file

@ -11,7 +11,7 @@
[![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik) [![Twitter](https://img.shields.io/twitter/follow/traefik.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefik)
Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. Traefik (pronounced _traffic_) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy.
Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically. Traefik integrates with your existing infrastructure components ([Docker](https://www.docker.com/), [Swarm mode](https://docs.docker.com/engine/swarm/), [Kubernetes](https://kubernetes.io), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Rancher v2](https://rancher.com), [Amazon ECS](https://aws.amazon.com/ecs), ...) and configures itself automatically and dynamically.
Pointing Traefik at your orchestrator should be the _only_ configuration step you need. Pointing Traefik at your orchestrator should be the _only_ configuration step you need.
--- ---
@ -58,7 +58,7 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t
- Circuit breakers, retry - Circuit breakers, retry
- See the magic through its clean web UI - See the magic through its clean web UI
- Websocket, HTTP/2, gRPC ready - Websocket, HTTP/2, gRPC ready
- Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB) - Provides metrics (Rest, Prometheus, Datadog, Statsd, InfluxDB 2.X)
- Keeps access logs (JSON, CLF) - Keeps access logs (JSON, CLF)
- Fast - Fast
- Exposes a Rest API - Exposes a Rest API
@ -68,8 +68,6 @@ _(But if you'd rather configure some of your routes manually, Traefik supports t
- [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/) - [Docker](https://doc.traefik.io/traefik/providers/docker/) / [Swarm mode](https://doc.traefik.io/traefik/providers/docker/)
- [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/) - [Kubernetes](https://doc.traefik.io/traefik/providers/kubernetes-crd/)
- [Marathon](https://doc.traefik.io/traefik/providers/marathon/)
- [Rancher](https://doc.traefik.io/traefik/providers/rancher/) (Metadata)
- [File](https://doc.traefik.io/traefik/providers/file/) - [File](https://doc.traefik.io/traefik/providers/file/)
## Quickstart ## Quickstart

View file

@ -523,16 +523,6 @@ func registerMetricClients(metricsConfig *types.Metrics) []metrics.Registry {
Msg("Configured StatsD metrics") Msg("Configured StatsD metrics")
} }
if metricsConfig.InfluxDB != nil {
logger := log.With().Str(logs.MetricsProviderName, "influxdb").Logger()
registries = append(registries, metrics.RegisterInfluxDB(logger.WithContext(context.Background()), metricsConfig.InfluxDB))
logger.Debug().
Str("address", metricsConfig.InfluxDB.Address).
Str("pushInterval", metricsConfig.InfluxDB.PushInterval.String()).
Msg("Configured InfluxDB metrics")
}
if metricsConfig.InfluxDB2 != nil { if metricsConfig.InfluxDB2 != nil {
logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger() logger := log.With().Str(logs.MetricsProviderName, "influxdb2").Logger()

View file

@ -15,7 +15,7 @@
"type": "grafana", "type": "grafana",
"id": "grafana", "id": "grafana",
"name": "Grafana", "name": "Grafana",
"version": "9.2.2" "version": "9.3.1"
}, },
{ {
"type": "panel", "type": "panel",
@ -64,8 +64,10 @@
} }
] ]
}, },
"editable": true, "description": "Official dashboard for Traefik on Kubernetes",
"editable": false,
"fiscalYearStartMonth": 0, "fiscalYearStartMonth": 0,
"gnetId": 17347,
"graphTooltip": 0, "graphTooltip": 0,
"id": null, "id": null,
"links": [], "links": [],
@ -133,7 +135,7 @@
}, },
"textMode": "auto" "textMode": "auto"
}, },
"pluginVersion": "9.2.2", "pluginVersion": "9.3.1",
"targets": [ "targets": [
{ {
"datasource": { "datasource": {
@ -818,7 +820,7 @@
"type": "row" "type": "row"
}, },
{ {
"collapsed": true, "collapsed": false,
"gridPos": { "gridPos": {
"h": 1, "h": 1,
"w": 24, "w": 24,
@ -826,7 +828,10 @@
"y": 18 "y": 18
}, },
"id": 16, "id": 16,
"panels": [ "panels": [],
"title": "HTTP Details",
"type": "row"
},
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
@ -887,10 +892,10 @@
"overrides": [] "overrides": []
}, },
"gridPos": { "gridPos": {
"h": 8, "h": 12,
"w": 12, "w": 8,
"x": 0, "x": 0,
"y": 27 "y": 19
}, },
"id": 17, "id": 17,
"options": { "options": {
@ -900,7 +905,7 @@
"max" "max"
], ],
"displayMode": "table", "displayMode": "table",
"placement": "right", "placement": "bottom",
"showLegend": true, "showLegend": true,
"sortBy": "Mean", "sortBy": "Mean",
"sortDesc": true "sortDesc": true
@ -987,10 +992,10 @@
"overrides": [] "overrides": []
}, },
"gridPos": { "gridPos": {
"h": 8, "h": 12,
"w": 12, "w": 8,
"x": 12, "x": 8,
"y": 27 "y": 19
}, },
"id": 18, "id": 18,
"options": { "options": {
@ -1000,7 +1005,7 @@
"max" "max"
], ],
"displayMode": "table", "displayMode": "table",
"placement": "right", "placement": "bottom",
"showLegend": true, "showLegend": true,
"sortBy": "Mean", "sortBy": "Mean",
"sortDesc": true "sortDesc": true
@ -1087,10 +1092,10 @@
"overrides": [] "overrides": []
}, },
"gridPos": { "gridPos": {
"h": 8, "h": 12,
"w": 12, "w": 8,
"x": 0, "x": 16,
"y": 35 "y": 19
}, },
"id": 19, "id": 19,
"options": { "options": {
@ -1100,7 +1105,7 @@
"max" "max"
], ],
"displayMode": "table", "displayMode": "table",
"placement": "right", "placement": "bottom",
"showLegend": true, "showLegend": true,
"sortBy": "Mean", "sortBy": "Mean",
"sortDesc": true "sortDesc": true
@ -1189,8 +1194,8 @@
"gridPos": { "gridPos": {
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 12, "x": 0,
"y": 35 "y": 31
}, },
"id": 20, "id": 20,
"options": { "options": {
@ -1226,6 +1231,106 @@
"title": "Requests Size", "title": "Requests Size",
"type": "timeseries" "type": "timeseries"
}, },
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisGridShow": true,
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "binBps"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 31
},
"id": 24,
"options": {
"legend": {
"calcs": [
"mean",
"max"
],
"displayMode": "table",
"placement": "right",
"showLegend": true,
"sortBy": "Mean",
"sortDesc": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}} on {{service}}",
"range": true,
"refId": "A"
}
],
"title": "Responses Size",
"type": "timeseries"
},
{ {
"datasource": { "datasource": {
"type": "prometheus", "type": "prometheus",
@ -1289,7 +1394,7 @@
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 0, "x": 0,
"y": 43 "y": 39
}, },
"id": 2, "id": 2,
"options": { "options": {
@ -1388,7 +1493,7 @@
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 12, "x": 12,
"y": 43 "y": 39
}, },
"id": 21, "id": 21,
"options": { "options": {
@ -1425,10 +1530,6 @@
"type": "timeseries" "type": "timeseries"
} }
], ],
"title": "HTTP Details",
"type": "row"
}
],
"refresh": false, "refresh": false,
"schemaVersion": 37, "schemaVersion": 37,
"style": "dark", "style": "dark",
@ -1504,8 +1605,8 @@
}, },
"timepicker": {}, "timepicker": {},
"timezone": "", "timezone": "",
"title": "Traefik Official Standalone Dashboard", "title": "Traefik Official Kubernetes Dashboard",
"uid": "n5bu_kv4k", "uid": "n5bu_kv4k",
"version": 3, "version": 5,
"weekStart": "" "weekStart": ""
} }

View file

@ -15,7 +15,7 @@
"type": "grafana", "type": "grafana",
"id": "grafana", "id": "grafana",
"name": "Grafana", "name": "Grafana",
"version": "9.2.2" "version": "9.3.1"
}, },
{ {
"type": "panel", "type": "panel",
@ -64,8 +64,10 @@
} }
] ]
}, },
"editable": true, "description": "Official dashboard for Standalone Traefik",
"editable": false,
"fiscalYearStartMonth": 0, "fiscalYearStartMonth": 0,
"gnetId": 17346,
"graphTooltip": 0, "graphTooltip": 0,
"id": null, "id": null,
"links": [], "links": [],
@ -133,7 +135,7 @@
}, },
"textMode": "auto" "textMode": "auto"
}, },
"pluginVersion": "9.2.2", "pluginVersion": "9.3.1",
"targets": [ "targets": [
{ {
"datasource": { "datasource": {
@ -669,8 +671,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
} }
] ]
}, },
@ -764,8 +765,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
} }
] ]
}, },
@ -873,8 +873,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
}, },
{ {
"color": "red", "color": "red",
@ -887,10 +886,10 @@
"overrides": [] "overrides": []
}, },
"gridPos": { "gridPos": {
"h": 8, "h": 12,
"w": 12, "w": 8,
"x": 0, "x": 0,
"y": 27 "y": 19
}, },
"id": 17, "id": 17,
"options": { "options": {
@ -900,7 +899,7 @@
"max" "max"
], ],
"displayMode": "table", "displayMode": "table",
"placement": "right", "placement": "bottom",
"showLegend": true, "showLegend": true,
"sortBy": "Mean", "sortBy": "Mean",
"sortDesc": true "sortDesc": true
@ -973,8 +972,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
}, },
{ {
"color": "red", "color": "red",
@ -987,10 +985,10 @@
"overrides": [] "overrides": []
}, },
"gridPos": { "gridPos": {
"h": 8, "h": 12,
"w": 12, "w": 8,
"x": 12, "x": 8,
"y": 27 "y": 19
}, },
"id": 18, "id": 18,
"options": { "options": {
@ -1000,7 +998,7 @@
"max" "max"
], ],
"displayMode": "table", "displayMode": "table",
"placement": "right", "placement": "bottom",
"showLegend": true, "showLegend": true,
"sortBy": "Mean", "sortBy": "Mean",
"sortDesc": true "sortDesc": true
@ -1073,8 +1071,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
}, },
{ {
"color": "red", "color": "red",
@ -1087,10 +1084,10 @@
"overrides": [] "overrides": []
}, },
"gridPos": { "gridPos": {
"h": 8, "h": 12,
"w": 12, "w": 8,
"x": 0, "x": 16,
"y": 35 "y": 19
}, },
"id": 19, "id": 19,
"options": { "options": {
@ -1100,7 +1097,7 @@
"max" "max"
], ],
"displayMode": "table", "displayMode": "table",
"placement": "right", "placement": "bottom",
"showLegend": true, "showLegend": true,
"sortBy": "Mean", "sortBy": "Mean",
"sortDesc": true "sortDesc": true
@ -1173,8 +1170,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
}, },
{ {
"color": "red", "color": "red",
@ -1189,8 +1185,8 @@
"gridPos": { "gridPos": {
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 12, "x": 0,
"y": 35 "y": 31
}, },
"id": 20, "id": 20,
"options": { "options": {
@ -1240,6 +1236,7 @@
"custom": { "custom": {
"axisCenteredZero": false, "axisCenteredZero": false,
"axisColorMode": "text", "axisColorMode": "text",
"axisGridShow": true,
"axisLabel": "", "axisLabel": "",
"axisPlacement": "auto", "axisPlacement": "auto",
"barAlignment": 0, "barAlignment": 0,
@ -1272,8 +1269,105 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null },
{
"color": "red",
"value": 80
}
]
},
"unit": "binBps"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 31
},
"id": 24,
"options": {
"legend": {
"calcs": [
"mean",
"max"
],
"displayMode": "table",
"placement": "right",
"showLegend": true,
"sortBy": "Mean",
"sortDesc": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "topk(15,\n label_replace(\n sum by (service,method) \n (rate(traefik_service_responses_bytes_total{service=~\"$service.*\",protocol=\"http\"}[1m])) > 0,\n \"service\", \"$1\", \"service\", \"([^-]+-[^-]+).*\")\n)",
"legendFormat": "{{method}} on {{service}}",
"range": true,
"refId": "A"
}
],
"title": "Responses Size",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
}, },
{ {
"color": "red", "color": "red",
@ -1289,7 +1383,7 @@
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 0, "x": 0,
"y": 43 "y": 39
}, },
"id": 2, "id": 2,
"options": { "options": {
@ -1371,8 +1465,7 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green", "color": "green"
"value": null
}, },
{ {
"color": "red", "color": "red",
@ -1388,7 +1481,7 @@
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 12, "x": 12,
"y": 43 "y": 39
}, },
"id": 21, "id": 21,
"options": { "options": {
@ -1491,7 +1584,7 @@
"refId": "StandardVariableQuery" "refId": "StandardVariableQuery"
}, },
"refresh": 2, "refresh": 2,
"regex": "/([^-]+-[^-]+).*/", "regex": "",
"skipUrlSync": false, "skipUrlSync": false,
"sort": 1, "sort": 1,
"type": "query" "type": "query"
@ -1505,7 +1598,7 @@
"timepicker": {}, "timepicker": {},
"timezone": "", "timezone": "",
"title": "Traefik Official Standalone Dashboard", "title": "Traefik Official Standalone Dashboard",
"uid": "n5bu_kv4k", "uid": "n5bu_kv45",
"version": 3, "version": 5,
"weekStart": "" "weekStart": ""
} }

View file

@ -107,7 +107,6 @@ The `status/*` labels represent the desired state in the workflow.
* `area/provider/kv`: KV related. * `area/provider/kv`: KV related.
* `area/provider/marathon`: Marathon related. * `area/provider/marathon`: Marathon related.
* `area/provider/mesos`: Mesos related. * `area/provider/mesos`: Mesos related.
* `area/provider/rancher`: Rancher related.
* `area/provider/servicefabric`: Azure service fabric related. * `area/provider/servicefabric`: Azure service fabric related.
* `area/provider/zk`: Zoo Keeper related. * `area/provider/zk`: Zoo Keeper related.
* `area/rules`: Rules related. * `area/rules`: Rules related.

View file

@ -43,27 +43,6 @@ spec:
- '*.example.org' - '*.example.org'
``` ```
```json tab="Marathon"
labels: {
"traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)",
"traefik.http.routers.blog.tls": "true",
"traefik.http.routers.blog.tls.certresolver": "myresolver",
"traefik.http.routers.blog.tls.domains[0].main": "example.com",
"traefik.http.routers.blog.tls.domains[0].sans": "*.example.com",
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
}
```
```yaml tab="Rancher"
## Dynamic configuration
labels:
- traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=myresolver
- traefik.http.routers.blog.tls.domains[0].main=example.org
- traefik.http.routers.blog.tls.domains[0].sans=*.example.org
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
http: http:

View file

@ -35,23 +35,6 @@ spec:
certResolver: myresolver certResolver: myresolver
``` ```
```json tab="Marathon"
labels: {
"traefik.http.routers.blog.rule": "(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`)",
"traefik.http.routers.blog.tls": "true",
"traefik.http.routers.blog.tls.certresolver": "myresolver",
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
}
```
```yaml tab="Rancher"
## Dynamic configuration
labels:
- traefik.http.routers.blog.rule=(Host(`example.com`) && Path(`/blog`)) || Host(`blog.example.org`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=myresolver
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
http: http:

View file

@ -35,23 +35,6 @@ spec:
certResolver: myresolver certResolver: myresolver
``` ```
```json tab="Marathon"
labels: {
"traefik.http.routers.blog.rule": "Host(`example.com`) && Path(`/blog`)",
"traefik.http.routers.blog.tls": "true",
"traefik.http.routers.blog.tls.certresolver": "myresolver",
"traefik.http.services.blog-svc.loadbalancer.server.port": "8080"
}
```
```yaml tab="Rancher"
## Dynamic configuration
labels:
- traefik.http.routers.blog.rule=Host(`example.com`) && Path(`/blog`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=myresolver
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
http: http:

View file

@ -120,20 +120,6 @@ A certificate resolver requests certificates for a set of domain names inferred
certResolver: myresolver certResolver: myresolver
``` ```
```json tab="Marathon"
labels: {
"traefik.http.routers.blog.rule": "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)",
"traefik.http.routers.blog.tls.certresolver": "myresolver",
}
```
```yaml tab="Rancher"
## Dynamic configuration
labels:
- traefik.http.routers.blog.rule=Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)
- traefik.http.routers.blog.tls.certresolver=myresolver
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
http: http:
@ -192,22 +178,6 @@ A certificate resolver requests certificates for a set of domain names inferred
- main: monitoring.yak-bebop.ts.net - main: monitoring.yak-bebop.ts.net
``` ```
```json tab="Marathon"
labels: {
"traefik.http.routers.blog.rule": "Path(`/metrics`)",
"traefik.http.routers.blog.tls.certresolver": "myresolver",
"traefik.http.routers.blog.tls.domains[0].main": "monitoring.yak-bebop.ts.net",
}
```
```yaml tab="Rancher"
## Dynamic configuration
labels:
- traefik.http.routers.blog.rule=Path(`/metrics`)
- traefik.http.routers.blog.tls.certresolver=myresolver
- traefik.http.routers.blog.tls.domains[0].main=monitoring.yak-bebop.ts.net
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
http: http:

View file

@ -219,14 +219,6 @@ labels:
- "traefik.tls.stores.default.defaultgeneratedcert.domain.sans=foo.example.org, bar.example.org" - "traefik.tls.stores.default.defaultgeneratedcert.domain.sans=foo.example.org, bar.example.org"
``` ```
```json tab="Marathon"
labels: {
"traefik.tls.stores.default.defaultgeneratedcert.resolver": "myresolver",
"traefik.tls.stores.default.defaultgeneratedcert.domain.main": "example.org",
"traefik.tls.stores.default.defaultgeneratedcert.domain.sans": "foo.example.org, bar.example.org",
}
```
## TLS Options ## TLS Options
The TLS options allow one to configure some parameters of the TLS connection. The TLS options allow one to configure some parameters of the TLS connection.

View file

@ -13,7 +13,7 @@ It receives requests on behalf of your system and finds out which components are
What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services. What sets Traefik apart, besides its many features, is that it automatically discovers the right configuration for your services.
The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request. The magic happens when Traefik inspects your infrastructure, where it finds relevant information and discovers which service serves which request.
Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.) Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, and [the list goes on](providers/overview.md); and can handle many at the same time. (It even works for legacy software running on bare metal.)
With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions). With Traefik, there is no need to maintain and synchronize a separate configuration file: everything happens automatically, in real time (no restarts, no connection interruptions).
With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state. With Traefik, you spend time developing and deploying new features to your system, not on configuring and maintaining its working state.

View file

@ -36,18 +36,6 @@ spec:
- "traefik.http.middlewares.add-foo.addprefix.prefix=/foo" - "traefik.http.middlewares.add-foo.addprefix.prefix=/foo"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.add-foo.addprefix.prefix": "/foo"
}
```
```yaml tab="Rancher"
# Prefixing with /foo
labels:
- "traefik.http.middlewares.add-foo.addprefix.prefix=/foo"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Prefixing with /foo # Prefixing with /foo
http: http:

View file

@ -41,18 +41,6 @@ spec:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
}
```
```yaml tab="Rancher"
# Declaring the user list
labels:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Declaring the user list # Declaring the user list
http: http:
@ -157,18 +145,6 @@ data:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
}
```
```yaml tab="Rancher"
# Declaring the user list
labels:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Declaring the user list # Declaring the user list
http: http:
@ -232,17 +208,6 @@ data:
- "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile" - "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.usersfile": "/path/to/my/usersfile"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -287,17 +252,6 @@ spec:
- "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm" - "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.realm": "MyRealm"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -336,12 +290,6 @@ spec:
- "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.my-auth.basicauth.headerField": "X-WebAuth-User"
}
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -380,17 +328,6 @@ spec:
- "traefik.http.middlewares.test-auth.basicauth.removeheader=true" - "traefik.http.middlewares.test-auth.basicauth.removeheader=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.removeheader": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.basicauth.removeheader=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -40,18 +40,6 @@ spec:
- "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000"
}
```
```yaml tab="Rancher"
# Sets the maximum request body to 2MB
labels:
- "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Sets the maximum request body to 2MB # Sets the maximum request body to 2MB
http: http:
@ -97,17 +85,6 @@ spec:
- "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000" - "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.limit.buffering.maxRequestBodyBytes": "2000000"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.limit.buffering.maxRequestBodyBytes=2000000"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -147,17 +124,6 @@ spec:
- "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000" - "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.limit.buffering.memRequestBodyBytes": "2000000"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.limit.buffering.memRequestBodyBytes=2000000"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -199,17 +165,6 @@ spec:
- "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000" - "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.limit.buffering.maxResponseBodyBytes": "2000000"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.limit.buffering.maxResponseBodyBytes=2000000"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -249,17 +204,6 @@ spec:
- "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000" - "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.limit.buffering.memResponseBodyBytes": "2000000"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.limit.buffering.memResponseBodyBytes=2000000"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -301,17 +245,6 @@ You can have the Buffering middleware replay the request using `retryExpression`
- "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2" - "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.limit.buffering.retryExpression": "IsNetworkError() && Attempts() < 2"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.limit.buffering.retryExpression=IsNetworkError() && Attempts() < 2"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -97,31 +97,6 @@ spec:
- "traefik.http.services.service1.loadbalancer.server.port=80" - "traefik.http.services.service1.loadbalancer.server.port=80"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.routers.router1.service": "service1",
"traefik.http.routers.router1.middlewares": "secured",
"traefik.http.routers.router1.rule": "Host(`mydomain`)",
"traefik.http.middlewares.secured.chain.middlewares": "https-only,known-ips,auth-users",
"traefik.http.middlewares.auth-users.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"traefik.http.middlewares.https-only.redirectscheme.scheme": "https",
"traefik.http.middlewares.known-ips.ipallowlist.sourceRange": "192.168.1.7,127.0.0.1/32",
"traefik.http.services.service1.loadbalancer.server.port": "80"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.routers.router1.service=service1"
- "traefik.http.routers.router1.middlewares=secured"
- "traefik.http.routers.router1.rule=Host(`mydomain`)"
- "traefik.http.middlewares.secured.chain.middlewares=https-only,known-ips,auth-users"
- "traefik.http.middlewares.auth-users.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
- "traefik.http.middlewares.https-only.redirectscheme.scheme=https"
- "traefik.http.middlewares.known-ips.ipallowlist.sourceRange=192.168.1.7,127.0.0.1/32"
- "traefik.http.services.service1.loadbalancer.server.port=80"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# ... # ...
http: http:

View file

@ -52,18 +52,6 @@ spec:
- "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100" - "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.latency-check.circuitbreaker.expression": "LatencyAtQuantileMS(50.0) > 100"
}
```
```yaml tab="Rancher"
# Latency Check
labels:
- "traefik.http.middlewares.latency-check.circuitbreaker.expression=LatencyAtQuantileMS(50.0) > 100"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Latency Check # Latency Check
http: http:

View file

@ -36,18 +36,6 @@ spec:
- "traefik.http.middlewares.test-compress.compress=true" - "traefik.http.middlewares.test-compress.compress=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-compress.compress": "true"
}
```
```yaml tab="Rancher"
# Enable compression
labels:
- "traefik.http.middlewares.test-compress.compress=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Enable compression # Enable compression
http: http:
@ -114,17 +102,6 @@ spec:
- "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream" - "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-compress.compress.excludedcontenttypes": "text/event-stream"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-compress.compress.excludedcontenttypes=text/event-stream"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -167,17 +144,6 @@ spec:
- "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200" - "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-compress.compress.minresponsebodybytes": 1200
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-compress.compress.minresponsebodybytes=1200"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -39,18 +39,6 @@ spec:
- "traefik.http.middlewares.autodetect.contenttype=true" - "traefik.http.middlewares.autodetect.contenttype=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.autodetect.contenttype": "true"
}
```
```yaml tab="Rancher"
# Enable auto-detection
labels:
- "traefik.http.middlewares.autodetect.contenttype=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Enable auto-detection # Enable auto-detection
http: http:

View file

@ -36,18 +36,6 @@ spec:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
}
```
```yaml tab="Rancher"
# Declaring the user list
labels:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Declaring the user list # Declaring the user list
http: http:
@ -114,17 +102,6 @@ data:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -186,17 +163,6 @@ data:
- "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile" - "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.usersfile": "/path/to/my/usersfile"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -241,17 +207,6 @@ spec:
- "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm" - "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.realm": "MyRealm"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -290,17 +245,6 @@ spec:
- "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.my-auth.digestauth.headerField": "X-WebAuth-User"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -339,17 +283,6 @@ spec:
- "traefik.http.middlewares.test-auth.digestauth.removeheader=true" - "traefik.http.middlewares.test-auth.digestauth.removeheader=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.removeheader": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.removeheader=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -48,22 +48,6 @@ spec:
- "traefik.http.middlewares.test-errors.errors.query=/{status}.html" - "traefik.http.middlewares.test-errors.errors.query=/{status}.html"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-errors.errors.status": "500-599",
"traefik.http.middlewares.test-errors.errors.service": "serviceError",
"traefik.http.middlewares.test-errors.errors.query": "/{status}.html"
}
```
```yaml tab="Rancher"
# Dynamic Custom Error Page for 5XX Status Code
labels:
- "traefik.http.middlewares.test-errors.errors.status=500-599"
- "traefik.http.middlewares.test-errors.errors.service=serviceError"
- "traefik.http.middlewares.test-errors.errors.query=/{status}.html"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Custom Error Page for 5XX # Custom Error Page for 5XX
http: http:

View file

@ -38,18 +38,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth"
}
```
```yaml tab="Rancher"
# Forward authentication to example.com
labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Forward authentication to example.com # Forward authentication to example.com
http: http:
@ -103,17 +91,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth" - "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.address": "https://example.com/auth"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://example.com/auth"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -152,17 +129,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -206,17 +172,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -262,17 +217,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-" - "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex": "^X-"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeadersRegex=^X-"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -323,17 +267,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader" - "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders": "Accept,X-CustomHeader"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.authRequestHeaders=Accept,X-CustomHeader"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -397,17 +330,6 @@ data:
- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt" - "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -467,19 +389,6 @@ data:
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert",
"traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -545,19 +454,6 @@ data:
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" - "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert",
"traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -609,17 +505,6 @@ spec:
- "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true" - "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -37,17 +37,6 @@ spec:
- "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*" - "traefik.http.middlewares.test-grpcweb.grpcWeb.allowOrigins=*"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-grpcweb.grpcweb.alloworigins": "*"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-grpcweb.grpcweb.alloworigins=*"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -44,19 +44,6 @@ spec:
- "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value" - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test",
"traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "value"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test"
- "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=value"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -109,21 +96,6 @@ spec:
- "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header=" - "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header="
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name": "test",
"traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header": "",
"traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header": "",
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Script-Name=test"
- "traefik.http.middlewares.testheader.headers.customrequestheaders.X-Custom-Request-Header="
- "traefik.http.middlewares.testheader.headers.customresponseheaders.X-Custom-Response-Header="
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -173,19 +145,6 @@ spec:
- "traefik.http.middlewares.testheader.headers.browserxssfilter=true" - "traefik.http.middlewares.testheader.headers.browserxssfilter=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.framedeny": "true",
"traefik.http.middlewares.testheader.headers.browserxssfilter": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.framedeny=true"
- "traefik.http.middlewares.testheader.headers.browserxssfilter=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -242,23 +201,6 @@ spec:
- "traefik.http.middlewares.testheader.headers.addvaryheader=true" - "traefik.http.middlewares.testheader.headers.addvaryheader=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.testheader.headers.accesscontrolallowmethods": "GET,OPTIONS,PUT",
"traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist": "https://foo.bar.org,https://example.org",
"traefik.http.middlewares.testheader.headers.accesscontrolmaxage": "100",
"traefik.http.middlewares.testheader.headers.addvaryheader": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=https://foo.bar.org,https://example.org"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -34,18 +34,6 @@ spec:
- "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10"
}
```
```yaml tab="Rancher"
# Limiting to 10 simultaneous connections
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Limiting to 10 simultaneous connections # Limiting to 10 simultaneous connections
http: http:
@ -89,18 +77,6 @@ spec:
- "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10" - "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-inflightreq.inflightreq.amount": "10"
}
```
```yaml tab="Rancher"
# Limiting to 10 simultaneous connections
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.amount=10"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Limiting to 10 simultaneous connections # Limiting to 10 simultaneous connections
http: http:
@ -165,17 +141,6 @@ spec:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2" - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth": "2"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.depth=2"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -232,17 +197,6 @@ spec:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -286,17 +240,6 @@ spec:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username" - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername": "username"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requestheadername=username"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -337,17 +280,6 @@ spec:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true" - "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-inflightreq.inflightreq.sourcecriterion.requesthost=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -35,18 +35,6 @@ spec:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7"
}
```
```yaml tab="Rancher"
# Accepts request from defined IP
labels:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Accepts request from defined IP # Accepts request from defined IP
http: http:
@ -120,20 +108,6 @@ spec:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2" - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32, 192.168.1.7",
"traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth": "2"
}
```
```yaml tab="Rancher"
# Allowlisting Based on `X-Forwarded-For` with `depth=2`
labels:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.depth=2"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Allowlisting Based on `X-Forwarded-For` with `depth=2` # Allowlisting Based on `X-Forwarded-For` with `depth=2`
http: http:
@ -197,18 +171,6 @@ spec:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7"
}
```
```yaml tab="Rancher"
# Exclude from `X-Forwarded-For`
labels:
- "traefik.http.middlewares.test-ipallowlist.ipallowlist.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Exclude from `X-Forwarded-For` # Exclude from `X-Forwarded-For`
http: http:

View file

@ -69,22 +69,6 @@ spec:
- "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo",
"traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon"
}
```
```yaml tab="Rancher"
# As a Rancher Label
labels:
# Create a middleware named `foo-add-prefix`
- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo"
# Apply the middleware named `foo-add-prefix` to the router named `router1`
- "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher"
```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
# As TOML Configuration File # As TOML Configuration File
[http.routers] [http.routers]

View file

@ -39,18 +39,6 @@ spec:
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem": "true"
}
```
```yaml tab="Rancher"
# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header.
labels:
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.pem=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Pass the pem in the `X-Forwarded-Tls-Client-Cert` header. # Pass the pem in the `X-Forwarded-Tls-Client-Cert` header.
http: http:
@ -146,52 +134,6 @@ http:
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true" - "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province": "true",
"traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber": "true"
}
```
```yaml tab="Rancher"
# Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header
labels:
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notafter=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.notbefore=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.sans=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.commonname=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.country=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.domaincomponent=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.locality=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organization=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.organizationalunit=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.province=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.subject.serialnumber=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.commonname=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.country=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.domaincomponent=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.locality=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.organization=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.province=true"
- "traefik.http.middlewares.test-passtlsclientcert.passtlsclientcert.info.issuer.serialnumber=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header # Pass all the available info in the `X-Forwarded-Tls-Client-Cert-Info` header
http: http:

View file

@ -40,21 +40,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50" - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.average": "100",
"traefik.http.middlewares.test-ratelimit.ratelimit.burst": "50"
}
```
```yaml tab="Rancher"
# Here, an average of 100 requests per second is allowed.
# In addition, a burst of 50 requests is allowed.
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.test-ratelimit.ratelimit.burst=50"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Here, an average of 100 requests per second is allowed. # Here, an average of 100 requests per second is allowed.
# In addition, a burst of 50 requests is allowed. # In addition, a burst of 50 requests is allowed.
@ -108,17 +93,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=100" - "traefik.http.middlewares.test-ratelimit.ratelimit.average=100"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.average": "100",
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=100"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# 100 reqs/s # 100 reqs/s
http: http:
@ -170,20 +144,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m" - "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.average": "6",
"traefik.http.middlewares.test-ratelimit.ratelimit.period": "1m",
}
```
```yaml tab="Rancher"
# 6 reqs/minute
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.average=6"
- "traefik.http.middlewares.test-ratelimit.ratelimit.period=1m"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# 6 reqs/minute # 6 reqs/minute
http: http:
@ -227,17 +187,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100" - "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.burst": "100",
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.burst=100"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -300,17 +249,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2" - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth": "2"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.depth=2"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -394,17 +332,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7" - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips": "127.0.0.1/32, 192.168.1.7"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.ipstrategy.excludedips=127.0.0.1/32, 192.168.1.7"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -448,17 +375,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username" - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername": "username"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requestheadername=username"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:
@ -499,17 +415,6 @@ spec:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true" - "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-ratelimit.ratelimit.sourcecriterion.requesthost=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -43,21 +43,6 @@ spec:
- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}" - "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-redirectregex.redirectregex.regex": "^http://localhost/(.*)",
"traefik.http.middlewares.test-redirectregex.redirectregex.replacement": "http://mydomain/${1}"
}
```
```yaml tab="Rancher"
# Redirect with domain replacement
# Note: all dollar signs need to be doubled for escaping.
labels:
- "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^http://localhost/(.*)"
- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=http://mydomain/$${1}"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Redirect with domain replacement # Redirect with domain replacement
http: http:

View file

@ -51,20 +51,6 @@ labels:
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https"
"traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true"
}
```
```yaml tab="Rancher"
# Redirect to https
labels:
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Redirect to https # Redirect to https
http: http:
@ -115,20 +101,6 @@ labels:
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent": "true"
}
```
```yaml tab="Rancher"
# Redirect to https
labels:
# ...
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.permanent=true"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Redirect to https # Redirect to https
http: http:
@ -174,18 +146,6 @@ labels:
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme": "https"
}
```
```yaml tab="Rancher"
# Redirect to https
labels:
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.scheme=https"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Redirect to https # Redirect to https
http: http:
@ -232,20 +192,6 @@ labels:
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443" - "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-redirectscheme.redirectscheme.port": "443"
}
```
```yaml tab="Rancher"
# Redirect to https
labels:
# ...
- "traefik.http.middlewares.test-redirectscheme.redirectscheme.port=443"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Redirect to https # Redirect to https
http: http:

View file

@ -38,18 +38,6 @@ spec:
- "traefik.http.middlewares.test-replacepath.replacepath.path=/foo" - "traefik.http.middlewares.test-replacepath.replacepath.path=/foo"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-replacepath.replacepath.path": "/foo"
}
```
```yaml tab="Rancher"
# Replace the path with /foo
labels:
- "traefik.http.middlewares.test-replacepath.replacepath.path=/foo"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Replace the path with /foo # Replace the path with /foo
http: http:

View file

@ -41,20 +41,6 @@ spec:
- "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1" - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-replacepathregex.replacepathregex.regex": "^/foo/(.*)",
"traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement": "/bar/$1"
}
```
```yaml tab="Rancher"
# Replace path with regex
labels:
- "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)"
- "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$1"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Replace path with regex # Replace path with regex
http: http:

View file

@ -43,20 +43,6 @@ spec:
- "traefik.http.middlewares.test-retry.retry.initialinterval=100ms" - "traefik.http.middlewares.test-retry.retry.initialinterval=100ms"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-retry.retry.attempts": "4",
"traefik.http.middlewares.test-retry.retry.initialinterval": "100ms",
}
```
```yaml tab="Rancher"
# Retry 4 times with exponential backoff
labels:
- "traefik.http.middlewares.test-retry.retry.attempts=4"
- "traefik.http.middlewares.test-retry.retry.initialinterval=100ms"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Retry 4 times with exponential backoff # Retry 4 times with exponential backoff
http: http:

View file

@ -40,18 +40,6 @@ spec:
- "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar" - "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-stripprefix.stripprefix.prefixes": "/foobar,/fiibar"
}
```
```yaml tab="Rancher"
# Strip prefix /foobar and /fiibar
labels:
- "traefik.http.middlewares.test-stripprefix.stripprefix.prefixes=/foobar,/fiibar"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Strip prefix /foobar and /fiibar # Strip prefix /foobar and /fiibar
http: http:

View file

@ -32,17 +32,6 @@ spec:
- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/" - "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex": "/foo/[a-z0-9]+/[0-9]+/"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-stripprefixregex.stripprefixregex.regex=/foo/[a-z0-9]+/[0-9]+/"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
http: http:
middlewares: middlewares:

View file

@ -66,22 +66,6 @@ spec:
- "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog" - "traefik.http.routers.router1.middlewares=foo-add-prefix@consulcatalog"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.foo-add-prefix.addprefix.prefix": "/foo",
"traefik.http.routers.router1.middlewares": "foo-add-prefix@marathon"
}
```
```yaml tab="Rancher"
# As a Rancher Label
labels:
# Create a middleware named `foo-add-prefix`
- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo"
# Apply the middleware named `foo-add-prefix` to the router named `router1`
- "traefik.http.routers.router1.middlewares=foo-add-prefix@rancher"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# As YAML Configuration File # As YAML Configuration File
http: http:

View file

@ -27,18 +27,6 @@ spec:
- "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10" - "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10"
``` ```
```json tab="Marathon"
"labels": {
"traefik.tcp.middlewares.test-inflightconn.inflightconn.amount": "10"
}
```
```yaml tab="Rancher"
# Limiting to 10 simultaneous connections.
labels:
- "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Limiting to 10 simultaneous connections. # Limiting to 10 simultaneous connections.
tcp: tcp:

View file

@ -35,18 +35,6 @@ spec:
- "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7" - "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
``` ```
```json tab="Marathon"
"labels": {
"traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange": "127.0.0.1/32,192.168.1.7"
}
```
```yaml tab="Rancher"
# Accepts request from defined IP
labels:
- "traefik.tcp.middlewares.test-ipallowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
# Accepts request from defined IP # Accepts request from defined IP
[tcp.middlewares] [tcp.middlewares]

View file

@ -70,22 +70,6 @@ spec:
- "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@consulcatalog" - "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@consulcatalog"
``` ```
```json tab="Marathon"
"labels": {
"traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7",
"traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@marathon"
}
```
```yaml tab="Rancher"
# As a Rancher Label
labels:
# Create a middleware named `foo-ip-allowlist`
- "traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=127.0.0.1/32, 192.168.1.7"
# Apply the middleware named `foo-ip-allowlist` to the router named `router1`
- "traefik.tcp.routers.router1.middlewares=foo-ip-allowlist@rancher"
```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
# As TOML Configuration File # As TOML Configuration File
[tcp.routers] [tcp.routers]

View file

@ -26,10 +26,10 @@ In v3, the reported status code for gRPC requests is now the value of the `Grpc-
- The `pilot` option has been removed from the static configuration. - The `pilot` option has been removed from the static configuration.
- The `tracing.datadog.globaltag` option has been removed. - The `tracing.datadog.globaltag` option has been removed.
- The `namespace` option of Consul, Consul Catalog and Nomad providers has been removed. - The `namespace` option of Consul, Consul Catalog and Nomad providers has been removed.
- The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Marathon, Consul Catalog, and Docker providers. - The `tls.caOptional` option has been removed from the ForwardAuth middleware, as well as from the HTTP, Consul, Etcd, Redis, ZooKeeper, Consul Catalog, and Docker providers.
- `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed. - `sslRedirect`, `sslTemporaryRedirect`, `sslHost`, `sslForceHost` and `featurePolicy` options of the Headers middleware have been removed.
- The `forceSlash` option of the StripPrefix middleware has been removed. - The `forceSlash` option of the StripPrefix middleware has been removed.
- the `preferServerCipherSuites` option has been removed. - The `preferServerCipherSuites` option has been removed.
## Matchers ## Matchers
@ -65,3 +65,18 @@ When using the KubernetesCRD provider, it is therefore necessary to update [RBAC
The TCP LoadBalancer `terminationDelay` option has been removed. The TCP LoadBalancer `terminationDelay` option has been removed.
This option can now be configured directly on the `TCPServersTransport` level, please take a look at this [documentation](../routing/services/index.md#terminationdelay) This option can now be configured directly on the `TCPServersTransport` level, please take a look at this [documentation](../routing/services/index.md#terminationdelay)
## Rancher v1
In v3, the rancher v1 provider has been removed because Rancher v1 is [no longer actively maintaned](https://rancher.com/docs/os/v1.x/en/support/) and v2 is supported as a standard Kubernetes provider.
Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query.
As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](../providers/kubernetes-crd.md) directly.
## Marathon provider
In v3, the Marathon provider has been removed.
## InfluxDB v1
In v3, the InfluxDB v1 metrics provider has been removed because InfluxDB v1.x maintenance [ended in 2021](https://www.influxdata.com/blog/influxdb-oss-and-enterprise-roadmap-update-from-influxdays-emea/).

View file

@ -1,268 +0,0 @@
---
title: "Traefik InfluxDB Documentation"
description: "Traefik supports several metrics backends, including InfluxDB. Learn how to implement it for observability in Traefik Proxy. Read the technical documentation."
---
# InfluxDB
To enable the InfluxDB:
```yaml tab="File (YAML)"
metrics:
influxDB: {}
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
```
```bash tab="CLI"
--metrics.influxdb=true
```
#### `address`
_Required, Default="localhost:8089"_
Address instructs exporter to send metrics to influxdb at this address.
```yaml tab="File (YAML)"
metrics:
influxDB:
address: localhost:8089
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
address = "localhost:8089"
```
```bash tab="CLI"
--metrics.influxdb.address=localhost:8089
```
#### `protocol`
_Required, Default="udp"_
InfluxDB's address protocol (udp or http).
```yaml tab="File (YAML)"
metrics:
influxDB:
protocol: udp
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
protocol = "udp"
```
```bash tab="CLI"
--metrics.influxdb.protocol=udp
```
#### `database`
_Optional, Default=""_
InfluxDB database used when protocol is http.
```yaml tab="File (YAML)"
metrics:
influxDB:
database: db
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
database = "db"
```
```bash tab="CLI"
--metrics.influxdb.database=db
```
#### `retentionPolicy`
_Optional, Default=""_
InfluxDB retention policy used when protocol is http.
```yaml tab="File (YAML)"
metrics:
influxDB:
retentionPolicy: two_hours
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
retentionPolicy = "two_hours"
```
```bash tab="CLI"
--metrics.influxdb.retentionPolicy=two_hours
```
#### `username`
_Optional, Default=""_
InfluxDB username (only with http).
```yaml tab="File (YAML)"
metrics:
influxDB:
username: john
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
username = "john"
```
```bash tab="CLI"
--metrics.influxdb.username=john
```
#### `password`
_Optional, Default=""_
InfluxDB password (only with http).
```yaml tab="File (YAML)"
metrics:
influxDB:
password: secret
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
password = "secret"
```
```bash tab="CLI"
--metrics.influxdb.password=secret
```
#### `addEntryPointsLabels`
_Optional, Default=true_
Enable metrics on entry points.
```yaml tab="File (YAML)"
metrics:
influxDB:
addEntryPointsLabels: true
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
addEntryPointsLabels = true
```
```bash tab="CLI"
--metrics.influxdb.addEntryPointsLabels=true
```
#### `addRoutersLabels`
_Optional, Default=false_
Enable metrics on routers.
```yaml tab="File (YAML)"
metrics:
influxDB:
addRoutersLabels: true
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
addRoutersLabels = true
```
```bash tab="CLI"
--metrics.influxdb.addrouterslabels=true
```
#### `addServicesLabels`
_Optional, Default=true_
Enable metrics on services.
```yaml tab="File (YAML)"
metrics:
influxDB:
addServicesLabels: true
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
addServicesLabels = true
```
```bash tab="CLI"
--metrics.influxdb.addServicesLabels=true
```
#### `pushInterval`
_Optional, Default=10s_
The interval used by the exporter to push metrics to influxdb.
```yaml tab="File (YAML)"
metrics:
influxDB:
pushInterval: 10s
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
pushInterval = "10s"
```
```bash tab="CLI"
--metrics.influxdb.pushInterval=10s
```
#### `additionalLabels`
_Optional, Default={}_
Additional labels (influxdb tags) on all metrics.
```yaml tab="File (YAML)"
metrics:
influxDB:
additionalLabels:
host: example.com
environment: production
```
```toml tab="File (TOML)"
[metrics]
[metrics.influxDB]
[metrics.influxDB.additionalLabels]
host = "example.com"
environment = "production"
```
```bash tab="CLI"
--metrics.influxdb.additionallabels.host=example.com --metrics.influxdb.additionallabels.environment=production
```

View file

@ -1,6 +1,6 @@
--- ---
title: "Traefik Metrics Overview" title: "Traefik Metrics Overview"
description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started." description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB 2.X, Prometheus, and StatsD. Read the full documentation to get started."
--- ---
# Metrics # Metrics
@ -8,7 +8,6 @@ description: "Traefik Proxy supports these metrics backend systems: Datadog, Inf
Traefik supports these metrics backends: Traefik supports these metrics backends:
- [Datadog](./datadog.md) - [Datadog](./datadog.md)
- [InfluxDB](./influxdb.md)
- [InfluxDB2](./influxdb2.md) - [InfluxDB2](./influxdb2.md)
- [Prometheus](./prometheus.md) - [Prometheus](./prometheus.md)
- [StatsD](./statsd.md) - [StatsD](./statsd.md)
@ -35,7 +34,7 @@ config.reload.lastSuccessTimestamp
tls.certs.notAfterTimestamp tls.certs.notAfterTimestamp
``` ```
```influxdb tab="InfluxDB / InfluxDB2" ```influxdb tab="InfluxDB2"
traefik.config.reload.total traefik.config.reload.total
traefik.config.reload.lastSuccessTimestamp traefik.config.reload.lastSuccessTimestamp
traefik.tls.certs.notAfterTimestamp traefik.tls.certs.notAfterTimestamp
@ -77,7 +76,7 @@ entrypoint.requests.bytes.total
entrypoint.responses.bytes.total entrypoint.responses.bytes.total
``` ```
```influxdb tab="InfluxDB / InfluxDB2" ```influxdb tab="InfluxDB2"
traefik.entrypoint.requests.total traefik.entrypoint.requests.total
traefik.entrypoint.requests.tls.total traefik.entrypoint.requests.tls.total
traefik.entrypoint.request.duration traefik.entrypoint.request.duration
@ -125,7 +124,7 @@ router.requests.bytes.total
router.responses.bytes.total router.responses.bytes.total
``` ```
```influxdb tab="InfluxDB / InfluxDB2" ```influxdb tab="InfluxDB2"
traefik.router.requests.total traefik.router.requests.total
traefik.router.requests.tls.total traefik.router.requests.tls.total
traefik.router.request.duration traefik.router.request.duration
@ -179,7 +178,7 @@ service.requests.bytes.total
service.responses.bytes.total service.responses.bytes.total
``` ```
```influxdb tab="InfluxDB / InfluxDB2" ```influxdb tab="InfluxDB2"
traefik.service.requests.total traefik.service.requests.total
traefik.service.requests.tls.total traefik.service.requests.tls.total
traefik.service.request.duration traefik.service.request.duration

View file

@ -51,24 +51,6 @@ spec:
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.routers.api.rule": "Host(`traefik.example.com`)",
"traefik.http.routers.api.service": "api@internal",
"traefik.http.routers.api.middlewares": "auth",
"traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
}
```
```yaml tab="Rancher"
# Dynamic Configuration
labels:
- "traefik.http.routers.api.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Dynamic Configuration # Dynamic Configuration
http: http:

View file

@ -51,24 +51,6 @@ spec:
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
``` ```
```json tab="Marathon"
"labels": {
"traefik.http.routers.dashboard.rule": "Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))",
"traefik.http.routers.dashboard.service": "api@internal",
"traefik.http.routers.dashboard.middlewares": "auth",
"traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
}
```
```yaml tab="Rancher"
# Dynamic Configuration
labels:
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Dynamic Configuration # Dynamic Configuration
http: http:

View file

@ -1,583 +0,0 @@
---
title: "Traefik Configuration for Marathon"
description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to learn how."
---
# Traefik & Marathon
Traefik can be configured to use Marathon as a provider.
{: .subtitle }
For additional information, refer to [Marathon user guide](../user-guides/marathon.md).
## Configuration Examples
??? example "Configuring Marathon & Deploying / Exposing Applications"
Enabling the Marathon provider
```yaml tab="File (YAML)"
providers:
marathon: {}
```
```toml tab="File (TOML)"
[providers.marathon]
```
```bash tab="CLI"
--providers.marathon=true
```
Attaching labels to Marathon applications
```json
{
"id": "/whoami",
"container": {
"type": "DOCKER",
"docker": {
"image": "traefik/whoami",
"network": "BRIDGE",
"portMappings": [
{
"containerPort": 80,
"hostPort": 0,
"protocol": "tcp"
}
]
}
},
"labels": {
"traefik.http.Routers.app.Rule": "PathPrefix(`/app`)"
}
}
```
## Routing Configuration
See the dedicated section in [routing](../routing/providers/marathon.md).
## Provider Configuration
### `basic`
_Optional_
Enables Marathon basic authentication.
```yaml tab="File (YAML)"
providers:
marathon:
basic:
httpBasicAuthUser: foo
httpBasicPassword: bar
```
```toml tab="File (TOML)"
[providers.marathon.basic]
httpBasicAuthUser = "foo"
httpBasicPassword = "bar"
```
```bash tab="CLI"
--providers.marathon.basic.httpbasicauthuser=foo
--providers.marathon.basic.httpbasicpassword=bar
```
### `dcosToken`
_Optional_
Datacenter Operating System (DCOS) Token for DCOS environment.
If set, it overrides the Authorization header.
```toml tab="File (YAML)"
providers:
marathon:
dcosToken: "xxxxxx"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
dcosToken = "xxxxxx"
# ...
```
```bash tab="CLI"
--providers.marathon.dcosToken=xxxxxx
```
### `defaultRule`
_Optional, Default=```Host(`{{ normalize .Name }}`)```_
The default host rule for all services.
For a given application, if no routing rule was defined by a label, it is defined by this `defaultRule` instead.
It must be a valid [Go template](https://pkg.go.dev/text/template/),
and can include [sprig template functions](https://masterminds.github.io/sprig/).
The app ID can be accessed with the `Name` identifier,
and the template has access to all the labels defined on this Marathon application.
```yaml tab="File (YAML)"
providers:
marathon:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```bash tab="CLI"
--providers.marathon.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
# ...
```
### `dialerTimeout`
_Optional, Default=5s_
Amount of time the Marathon provider should wait before timing out,
when trying to open a TCP connection to a Marathon master.
The value of `dialerTimeout` should be provided in seconds or as a valid duration format,
see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration).
```yaml tab="File (YAML)"
providers:
marathon:
dialerTimeout: "10s"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
dialerTimeout = "10s"
# ...
```
```bash tab="CLI"
--providers.marathon.dialerTimeout=10s
```
### `endpoint`
_Optional, Default=http://127.0.0.1:8080_
Marathon server endpoint.
You can optionally specify multiple endpoints.
```yaml tab="File (YAML)"
providers:
marathon:
endpoint: "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
endpoint = "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080"
# ...
```
```bash tab="CLI"
--providers.marathon.endpoint=http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080
```
### `exposedByDefault`
_Optional, Default=true_
Exposes Marathon applications by default through Traefik.
If set to `false`, applications that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration.
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
```yaml tab="File (YAML)"
providers:
marathon:
exposedByDefault: false
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
exposedByDefault = false
# ...
```
```bash tab="CLI"
--providers.marathon.exposedByDefault=false
# ...
```
### `constraints`
_Optional, Default=""_
The `constraints` option can be set to an expression that Traefik matches against the application labels to determine whether
to create any route for that application. If none of the application labels match the expression, no route for that application is
created. In addition, the expression is also matched against the application constraints, such as described
in [Marathon constraints](https://mesosphere.github.io/marathon/docs/constraints.html).
If the expression is empty, all detected applications are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic.
In addition, to match against Marathon constraints, the function `MarathonConstraint("field:operator:value")` can be used, where the field, operator, and value parts are concatenated in a single string using the `:` separator.
??? example "Constraints Expression Examples"
```toml
# Includes only applications having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
```
```toml
# Excludes applications having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```
```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```
```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```
```toml
# Includes only applications having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```
```toml
# Includes only applications having a Marathon constraint with field `A`, operator `B`, and value `C`.
constraints = "MarathonConstraint(`A:B:C`)"
```
```toml
# Uses both Marathon constraint and application label with logical operator.
constraints = "MarathonConstraint(`A:B:C`) && Label(`a.label.name`, `value`)"
```
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
```yaml tab="File (YAML)"
providers:
marathon:
constraints: "Label(`a.label.name`,`foo`)"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
constraints = "Label(`a.label.name`,`foo`)"
# ...
```
```bash tab="CLI"
--providers.marathon.constraints=Label(`a.label.name`,`foo`)
# ...
```
### `forceTaskHostname`
_Optional, Default=false_
By default, the task IP address (as returned by the Marathon API) is used as backend server if an IP-per-task configuration can be found;
otherwise, the name of the host running the task is used.
The latter behavior can be enforced by setting this option to `true`.
```yaml tab="File (YAML)"
providers:
marathon:
forceTaskHostname: true
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
forceTaskHostname = true
# ...
```
```bash tab="CLI"
--providers.marathon.forceTaskHostname=true
# ...
```
### `keepAlive`
_Optional, Default=10s_
Set the TCP Keep Alive duration for the Marathon HTTP Client.
The value of `keepAlive` should be provided in seconds or as a valid duration format,
see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration).
```yaml tab="File (YAML)"
providers:
marathon:
keepAlive: "30s"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
keepAlive = "30s"
# ...
```
```bash tab="CLI"
--providers.marathon.keepAlive=30s
# ...
```
### `respectReadinessChecks`
_Optional, Default=false_
Applications may define readiness checks which are probed by Marathon during deployments periodically, and these check results are exposed via the API.
Enabling `respectReadinessChecks` causes Traefik to filter out tasks whose readiness checks have not succeeded.
Note that the checks are only valid during deployments.
See the Marathon guide for details.
```yaml tab="File (YAML)"
providers:
marathon:
respectReadinessChecks: true
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
respectReadinessChecks = true
# ...
```
```bash tab="CLI"
--providers.marathon.respectReadinessChecks=true
# ...
```
### `responseHeaderTimeout`
_Optional, Default=60s_
Amount of time the Marathon provider should wait before timing out when waiting for the first response header
from a Marathon master.
The value of `responseHeaderTimeout` should be provided in seconds or as a valid duration format,
see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration).
```yaml tab="File (YAML)"
providers:
marathon:
responseHeaderTimeout: "66s"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
responseHeaderTimeout = "66s"
# ...
```
```bash tab="CLI"
--providers.marathon.responseHeaderTimeout=66s
# ...
```
### `tls`
_Optional_
Defines the TLS configuration used for the secure connection to Marathon.
#### `ca`
`ca` is the path to the certificate authority used for the secure connection to Marathon,
it defaults to the system bundle.
```yaml tab="File (YAML)"
providers:
marathon:
tls:
ca: path/to/ca.crt
```
```toml tab="File (TOML)"
[providers.marathon.tls]
ca = "path/to/ca.crt"
```
```bash tab="CLI"
--providers.marathon.tls.ca=path/to/ca.crt
```
#### `cert`
_Optional_
`cert` is the path to the public certificate used for the secure connection to Marathon.
When using this option, setting the `key` option is required.
```yaml tab="File (YAML)"
providers:
marathon:
tls:
cert: path/to/foo.cert
key: path/to/foo.key
```
```toml tab="File (TOML)"
[providers.marathon.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
```
```bash tab="CLI"
--providers.marathon.tls.cert=path/to/foo.cert
--providers.marathon.tls.key=path/to/foo.key
```
#### `key`
_Optional_
`key` is the path to the private key used for the secure connection to Marathon.
When using this option, setting the `cert` option is required.
```yaml tab="File (YAML)"
providers:
marathon:
tls:
cert: path/to/foo.cert
key: path/to/foo.key
```
```toml tab="File (TOML)"
[providers.marathon.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
```
```bash tab="CLI"
--providers.marathon.tls.cert=path/to/foo.cert
--providers.marathon.tls.key=path/to/foo.key
```
#### `insecureSkipVerify`
_Optional, Default=false_
If `insecureSkipVerify` is `true`, the TLS connection to Marathon accepts any certificate presented by the server regardless of the hostnames it covers.
```yaml tab="File (YAML)"
providers:
marathon:
tls:
insecureSkipVerify: true
```
```toml tab="File (TOML)"
[providers.marathon.tls]
insecureSkipVerify = true
```
```bash tab="CLI"
--providers.marathon.tls.insecureSkipVerify=true
```
### `tlsHandshakeTimeout`
_Optional, Default=5s_
Amount of time the Marathon provider should wait before timing out,
when waiting for the TLS handshake to complete.
The value of `tlsHandshakeTimeout` should be provided in seconds or as a valid duration format,
see [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration).
```yaml tab="File (YAML)"
providers:
marathon:
tlsHandshakeTimeout: "10s"
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
tlsHandshakeTimeout = "10s"
# ...
```
```bash tab="CLI"
--providers.marathon.tlsHandshakeTimeout=10s
# ...
```
### `trace`
_Optional, Default=false_
Displays additional provider logs when available.
```yaml tab="File (YAML)"
providers:
marathon:
trace: true
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
trace = true
# ...
```
```bash tab="CLI"
--providers.marathon.trace=true
# ...
```
### `watch`
_Optional, Default=true_
When set to `true`, watches for Marathon changes.
```yaml tab="File (YAML)"
providers:
marathon:
watch: false
# ...
```
```toml tab="File (TOML)"
[providers.marathon]
watch = false
# ...
```
```bash tab="CLI"
--providers.marathon.watch=false
# ...
```

View file

@ -141,8 +141,6 @@ Below is the list of the currently supported providers in Traefik.
| [Consul Catalog](./consul-catalog.md) | Orchestrator | Label | `consulcatalog` | | [Consul Catalog](./consul-catalog.md) | Orchestrator | Label | `consulcatalog` |
| [Nomad](./nomad.md) | Orchestrator | Label | `nomad` | | [Nomad](./nomad.md) | Orchestrator | Label | `nomad` |
| [ECS](./ecs.md) | Orchestrator | Label | `ecs` | | [ECS](./ecs.md) | Orchestrator | Label | `ecs` |
| [Marathon](./marathon.md) | Orchestrator | Label | `marathon` |
| [Rancher](./rancher.md) | Orchestrator | Label | `rancher` |
| [File](./file.md) | Manual | YAML/TOML format | `file` | | [File](./file.md) | Manual | YAML/TOML format | `file` |
| [Consul](./consul.md) | KV | KV | `consul` | | [Consul](./consul.md) | KV | KV | `consul` |
| [Etcd](./etcd.md) | KV | KV | `etcd` | | [Etcd](./etcd.md) | KV | KV | `etcd` |
@ -216,8 +214,6 @@ List of providers that support these features:
- [ECS](./ecs.md#exposedbydefault) - [ECS](./ecs.md#exposedbydefault)
- [Consul Catalog](./consul-catalog.md#exposedbydefault) - [Consul Catalog](./consul-catalog.md#exposedbydefault)
- [Nomad](./nomad.md#exposedbydefault) - [Nomad](./nomad.md#exposedbydefault)
- [Rancher](./rancher.md#exposedbydefault)
- [Marathon](./marathon.md#exposedbydefault)
### Constraints ### Constraints
@ -227,8 +223,6 @@ List of providers that support constraints:
- [ECS](./ecs.md#constraints) - [ECS](./ecs.md#constraints)
- [Consul Catalog](./consul-catalog.md#constraints) - [Consul Catalog](./consul-catalog.md#constraints)
- [Nomad](./nomad.md#constraints) - [Nomad](./nomad.md#constraints)
- [Rancher](./rancher.md#constraints)
- [Marathon](./marathon.md#constraints)
- [Kubernetes CRD](./kubernetes-crd.md#labelselector) - [Kubernetes CRD](./kubernetes-crd.md#labelselector)
- [Kubernetes Ingress](./kubernetes-ingress.md#labelselector) - [Kubernetes Ingress](./kubernetes-ingress.md#labelselector)
- [Kubernetes Gateway](./kubernetes-gateway.md#labelselector) - [Kubernetes Gateway](./kubernetes-gateway.md#labelselector)

View file

@ -1,286 +0,0 @@
---
title: ""Traefik Configuration Discovery: Rancher""
description: "Read the official Traefik documentation to learn how to expose Rancher services by default in Traefik Proxy."
---
# Traefik & Rancher
A Story of Labels, Services & Containers
{: .subtitle }
![Rancher](../assets/img/providers/rancher.png)
Attach labels to your services and let Traefik do the rest!
!!! important "This provider is specific to Rancher 1.x."
Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query.
As such, Rancher 2.x users should utilize the [Kubernetes CRD provider](./kubernetes-crd.md) directly.
## Configuration Examples
??? example "Configuring Rancher & Deploying / Exposing Services"
Enabling the Rancher provider
```yaml tab="File (YAML)"
providers:
rancher: {}
```
```toml tab="File (TOML)"
[providers.rancher]
```
```bash tab="CLI"
--providers.rancher=true
```
Attaching labels to services
```yaml
labels:
- traefik.http.services.my-service.rule=Host(`example.com`)
```
## Routing Configuration
See the dedicated section in [routing](../routing/providers/rancher.md).
## Provider Configuration
??? tip "Browse the Reference"
For an overview of all the options that can be set with the Rancher provider, see the following snippets:
```yaml tab="File (YAML)"
--8<-- "content/providers/rancher.yml"
```
```toml tab="File (TOML)"
--8<-- "content/providers/rancher.toml"
```
```bash tab="CLI"
--8<-- "content/providers/rancher.txt"
```
### `exposedByDefault`
_Optional, Default=true_
Expose Rancher services by default in Traefik.
If set to `false`, services that do not have a `traefik.enable=true` label are ignored from the resulting routing configuration.
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
```yaml tab="File (YAML)"
providers:
rancher:
exposedByDefault: false
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
exposedByDefault = false
# ...
```
```bash tab="CLI"
--providers.rancher.exposedByDefault=false
# ...
```
### `defaultRule`
_Optional, Default=```Host(`{{ normalize .Name }}`)```_
The default host rule for all services.
The `defaultRule` option defines what routing rule to apply to a container if no rule is defined by a label.
It must be a valid [Go template](https://pkg.go.dev/text/template/), and can use
[sprig template functions](https://masterminds.github.io/sprig/).
The service name can be accessed with the `Name` identifier,
and the template has access to all the labels defined on this container.
This option can be overridden on a container basis with the `traefik.http.routers.Router1.rule` label.
```yaml tab="File (YAML)"
providers:
rancher:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
```
```bash tab="CLI"
--providers.rancher.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
# ...
```
### `enableServiceHealthFilter`
_Optional, Default=true_
Filter out services with unhealthy states and inactive states.
```yaml tab="File (YAML)"
providers:
rancher:
enableServiceHealthFilter: false
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
enableServiceHealthFilter = false
# ...
```
```bash tab="CLI"
--providers.rancher.enableServiceHealthFilter=false
# ...
```
### `refreshSeconds`
_Optional, Default=15_
Defines the polling interval (in seconds).
```yaml tab="File (YAML)"
providers:
rancher:
refreshSeconds: 30
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
refreshSeconds = 30
# ...
```
```bash tab="CLI"
--providers.rancher.refreshSeconds=30
# ...
```
### `intervalPoll`
_Optional, Default=false_
Poll the Rancher metadata service for changes every `rancher.refreshSeconds`,
which is less accurate than the default long polling technique which provides near instantaneous updates to Traefik.
```yaml tab="File (YAML)"
providers:
rancher:
intervalPoll: true
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
intervalPoll = true
# ...
```
```bash tab="CLI"
--providers.rancher.intervalPoll=true
# ...
```
### `prefix`
_Optional, Default="/latest"_
Prefix used for accessing the Rancher metadata service.
```yaml tab="File (YAML)"
providers:
rancher:
prefix: "/test"
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
prefix = "/test"
# ...
```
```bash tab="CLI"
--providers.rancher.prefix=/test
# ...
```
### `constraints`
_Optional, Default=""_
The `constraints` option can be set to an expression that Traefik matches against the container labels to determine whether
to create any route for that container. If none of the container tags match the expression, no route for that container is
created. If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as
the usual boolean logic, as shown in examples below.
??? example "Constraints Expression Examples"
```toml
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
```
```toml
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```
```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```
```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```
```toml
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
```yaml tab="File (YAML)"
providers:
rancher:
constraints: "Label(`a.label.name`,`foo`)"
# ...
```
```toml tab="File (TOML)"
[providers.rancher]
constraints = "Label(`a.label.name`,`foo`)"
# ...
```
```bash tab="CLI"
--providers.rancher.constraints=Label(`a.label.name`,`foo`)
# ...
```

View file

@ -1,20 +0,0 @@
# Enable Rancher Provider.
[providers.rancher]
# Expose Rancher services by default in Traefik.
exposedByDefault = true
# Enable watch Rancher changes.
watch = true
# Filter services with unhealthy states and inactive states.
enableServiceHealthFilter = true
# Defines the polling interval (in seconds).
refreshSeconds = 15
# Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate
intervalPoll = false
# Prefix used for accessing the Rancher metadata service
prefix = "/latest"

View file

@ -1,20 +0,0 @@
# Enable Rancher Provider.
--providers.rancher=true
# Expose Rancher services by default in Traefik.
--providers.rancher.exposedByDefault=true
# Enable watch Rancher changes.
--providers.rancher.watch=true
# Filter services with unhealthy states and inactive states.
--providers.rancher.enableServiceHealthFilter=true
# Defines the polling interval (in seconds).
--providers.rancher.refreshSeconds=15
# Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate
--providers.rancher.intervalPoll=false
# Prefix used for accessing the Rancher metadata service
--providers.rancher.prefix=/latest

View file

@ -1,21 +0,0 @@
# Enable Rancher Provider.
providers:
rancher:
# Expose Rancher services by default in Traefik.
exposedByDefault: true
# Enable watch Rancher changes.
watch: true
# Filter services with unhealthy states and inactive states.
enableServiceHealthFilter: true
# Defines the polling interval (in seconds).
refreshSeconds: 15
# Poll the Rancher metadata service for changes every `rancher.refreshSeconds`, which is less accurate
intervalPoll: false
# Prefix used for accessing the Rancher metadata service
prefix: /latest

View file

@ -1,210 +0,0 @@
"traefik.http.middlewares.middleware00.addprefix.prefix": "foobar",
"traefik.http.middlewares.middleware01.basicauth.headerfield": "foobar",
"traefik.http.middlewares.middleware01.basicauth.realm": "foobar",
"traefik.http.middlewares.middleware01.basicauth.removeheader": "true",
"traefik.http.middlewares.middleware01.basicauth.users": "foobar, foobar",
"traefik.http.middlewares.middleware01.basicauth.usersfile": "foobar",
"traefik.http.middlewares.middleware02.buffering.maxrequestbodybytes": "42",
"traefik.http.middlewares.middleware02.buffering.maxresponsebodybytes": "42",
"traefik.http.middlewares.middleware02.buffering.memrequestbodybytes": "42",
"traefik.http.middlewares.middleware02.buffering.memresponsebodybytes": "42",
"traefik.http.middlewares.middleware02.buffering.retryexpression": "foobar",
"traefik.http.middlewares.middleware03.chain.middlewares": "foobar, foobar",
"traefik.http.middlewares.middleware04.circuitbreaker.expression": "foobar",
"traefik.http.middlewares.middleware04.circuitbreaker.checkperiod": "42s",
"traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration": "42s",
"traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration": "42s",
"traefik.http.middlewares.middleware05.compress": "true",
"traefik.http.middlewares.middleware05.compress.excludedcontenttypes": "foobar, foobar",
"traefik.http.middlewares.middleware05.compress.minresponsebodybytes": "42",
"traefik.http.middlewares.middleware06.contenttype": "true",
"traefik.http.middlewares.middleware07.digestauth.headerfield": "foobar",
"traefik.http.middlewares.middleware07.digestauth.realm": "foobar",
"traefik.http.middlewares.middleware07.digestauth.removeheader": "true",
"traefik.http.middlewares.middleware07.digestauth.users": "foobar, foobar",
"traefik.http.middlewares.middleware07.digestauth.usersfile": "foobar",
"traefik.http.middlewares.middleware08.errors.query": "foobar",
"traefik.http.middlewares.middleware08.errors.service": "foobar",
"traefik.http.middlewares.middleware08.errors.status": "foobar, foobar",
"traefik.http.middlewares.middleware09.forwardauth.address": "foobar",
"traefik.http.middlewares.middleware09.forwardauth.authrequestheaders": "foobar, foobar",
"traefik.http.middlewares.middleware09.forwardauth.authresponseheaders": "foobar, foobar",
"traefik.http.middlewares.middleware09.forwardauth.authresponseheadersregex": "foobar",
"traefik.http.middlewares.middleware09.forwardauth.tls.ca": "foobar",
"traefik.http.middlewares.middleware09.forwardauth.tls.cert": "foobar",
"traefik.http.middlewares.middleware09.forwardauth.tls.insecureskipverify": "true",
"traefik.http.middlewares.middleware09.forwardauth.tls.key": "foobar",
"traefik.http.middlewares.middleware09.forwardauth.trustforwardheader": "true",
"traefik.http.middlewares.middleware10.headers.accesscontrolallowcredentials": "true",
"traefik.http.middlewares.middleware10.headers.accesscontrolallowheaders": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.accesscontrolmaxage": "42",
"traefik.http.middlewares.middleware10.headers.addvaryheader": "true",
"traefik.http.middlewares.middleware10.headers.allowedhosts": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.browserxssfilter": "true",
"traefik.http.middlewares.middleware10.headers.contentsecuritypolicy": "foobar",
"traefik.http.middlewares.middleware10.headers.contenttypenosniff": "true",
"traefik.http.middlewares.middleware10.headers.custombrowserxssvalue": "foobar",
"traefik.http.middlewares.middleware10.headers.customframeoptionsvalue": "foobar",
"traefik.http.middlewares.middleware10.headers.customrequestheaders.name0": "foobar",
"traefik.http.middlewares.middleware10.headers.customrequestheaders.name1": "foobar",
"traefik.http.middlewares.middleware10.headers.customresponseheaders.name0": "foobar",
"traefik.http.middlewares.middleware10.headers.customresponseheaders.name1": "foobar",
"traefik.http.middlewares.middleware10.headers.forcestsheader": "true",
"traefik.http.middlewares.middleware10.headers.framedeny": "true",
"traefik.http.middlewares.middleware10.headers.hostsproxyheaders": "foobar, foobar",
"traefik.http.middlewares.middleware10.headers.isdevelopment": "true",
"traefik.http.middlewares.middleware10.headers.permissionspolicy": "foobar",
"traefik.http.middlewares.middleware10.headers.publickey": "foobar",
"traefik.http.middlewares.middleware10.headers.referrerpolicy": "foobar",
"traefik.http.middlewares.middleware10.headers.sslproxyheaders.name0": "foobar",
"traefik.http.middlewares.middleware10.headers.sslproxyheaders.name1": "foobar",
"traefik.http.middlewares.middleware10.headers.stsincludesubdomains": "true",
"traefik.http.middlewares.middleware10.headers.stspreload": "true",
"traefik.http.middlewares.middleware10.headers.stsseconds": "42",
"traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.depth": "42",
"traefik.http.middlewares.middleware11.ipallowlist.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware11.ipallowlist.sourcerange": "foobar, foobar",
"traefik.http.middlewares.middleware12.inflightreq.amount": "42",
"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.depth": "42",
"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.requestheadername": "foobar",
"traefik.http.middlewares.middleware12.inflightreq.sourcecriterion.requesthost": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.commonname": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.country": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.domaincomponent": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.locality": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.organization": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.province": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.issuer.serialnumber": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.notafter": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.notbefore": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.sans": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.serialnumber": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.commonname": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.country": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.domaincomponent": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.locality": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organization": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.organizationalunit": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.province": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.info.subject.serialnumber": "true",
"traefik.http.middlewares.middleware13.passtlsclientcert.pem": "true",
"traefik.http.middlewares.middleware14.plugin.foobar.foo": "bar",
"traefik.http.middlewares.middleware15.ratelimit.average": "42",
"traefik.http.middlewares.middleware15.ratelimit.burst": "42",
"traefik.http.middlewares.middleware15.ratelimit.period": "42",
"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.ipstrategy.depth": "42",
"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.ipstrategy.excludedips": "foobar, foobar",
"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.requestheadername": "foobar",
"traefik.http.middlewares.middleware15.ratelimit.sourcecriterion.requesthost": "true",
"traefik.http.middlewares.middleware16.redirectregex.permanent": "true",
"traefik.http.middlewares.middleware16.redirectregex.regex": "foobar",
"traefik.http.middlewares.middleware16.redirectregex.replacement": "foobar",
"traefik.http.middlewares.middleware17.redirectscheme.permanent": "true",
"traefik.http.middlewares.middleware17.redirectscheme.port": "foobar",
"traefik.http.middlewares.middleware17.redirectscheme.scheme": "foobar",
"traefik.http.middlewares.middleware18.replacepath.path": "foobar",
"traefik.http.middlewares.middleware19.replacepathregex.regex": "foobar",
"traefik.http.middlewares.middleware19.replacepathregex.replacement": "foobar",
"traefik.http.middlewares.middleware20.retry.attempts": "42",
"traefik.http.middlewares.middleware20.retry.initialinterval": "42",
"traefik.http.middlewares.middleware21.stripprefix.prefixes": "foobar, foobar",
"traefik.http.middlewares.middleware22.stripprefixregex.regex": "foobar, foobar",
"traefik.http.middlewares.middleware23.grpcweb.alloworigins": "foobar, foobar",
"traefik.http.routers.router0.entrypoints": "foobar, foobar",
"traefik.http.routers.router0.middlewares": "foobar, foobar",
"traefik.http.routers.router0.priority": "42",
"traefik.http.routers.router0.rule": "foobar",
"traefik.http.routers.router0.service": "foobar",
"traefik.http.routers.router0.tls": "true",
"traefik.http.routers.router0.tls.certresolver": "foobar",
"traefik.http.routers.router0.tls.domains[0].main": "foobar",
"traefik.http.routers.router0.tls.domains[0].sans": "foobar, foobar",
"traefik.http.routers.router0.tls.domains[1].main": "foobar",
"traefik.http.routers.router0.tls.domains[1].sans": "foobar, foobar",
"traefik.http.routers.router0.tls.options": "foobar",
"traefik.http.routers.router1.entrypoints": "foobar, foobar",
"traefik.http.routers.router1.middlewares": "foobar, foobar",
"traefik.http.routers.router1.priority": "42",
"traefik.http.routers.router1.rule": "foobar",
"traefik.http.routers.router1.service": "foobar",
"traefik.http.routers.router1.tls": "true",
"traefik.http.routers.router1.tls.certresolver": "foobar",
"traefik.http.routers.router1.tls.domains[0].main": "foobar",
"traefik.http.routers.router1.tls.domains[0].sans": "foobar, foobar",
"traefik.http.routers.router1.tls.domains[1].main": "foobar",
"traefik.http.routers.router1.tls.domains[1].sans": "foobar, foobar",
"traefik.http.routers.router1.tls.options": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.followredirects": "true",
"traefik.http.services.service01.loadbalancer.healthcheck.headers.name0": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.headers.name1": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.hostname": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.interval": "42s",
"traefik.http.services.service01.loadbalancer.healthcheck.path": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.method": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.status": "42",
"traefik.http.services.service01.loadbalancer.healthcheck.port": "42",
"traefik.http.services.service01.loadbalancer.healthcheck.scheme": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.mode": "foobar",
"traefik.http.services.service01.loadbalancer.healthcheck.timeout": "42s",
"traefik.http.services.service01.loadbalancer.passhostheader": "true",
"traefik.http.services.service01.loadbalancer.responseforwarding.flushinterval": "42s",
"traefik.http.services.service01.loadbalancer.serverstransport": "foobar",
"traefik.http.services.service01.loadbalancer.sticky.cookie": "true",
"traefik.http.services.service01.loadbalancer.sticky.cookie.httponly": "true",
"traefik.http.services.service01.loadbalancer.sticky.cookie.name": "foobar",
"traefik.http.services.service01.loadbalancer.sticky.cookie.samesite": "foobar",
"traefik.http.services.service01.loadbalancer.sticky.cookie.secure": "true",
"traefik.http.services.service01.loadbalancer.server.port": "foobar",
"traefik.http.services.service01.loadbalancer.server.scheme": "foobar",
"traefik.tcp.middlewares.tcpmiddleware00.ipallowlist.sourcerange": "foobar, foobar",
"traefik.tcp.middlewares.tcpmiddleware01.inflightconn.amount": "42",
"traefik.tcp.routers.tcprouter0.entrypoints": "foobar, foobar",
"traefik.tcp.routers.tcprouter0.middlewares": "foobar, foobar",
"traefik.tcp.routers.tcprouter0.rule": "foobar",
"traefik.tcp.routers.tcprouter0.priority": "42",
"traefik.tcp.routers.tcprouter0.service": "foobar",
"traefik.tcp.routers.tcprouter0.tls": "true",
"traefik.tcp.routers.tcprouter0.tls.certresolver": "foobar",
"traefik.tcp.routers.tcprouter0.tls.domains[0].main": "foobar",
"traefik.tcp.routers.tcprouter0.tls.domains[0].sans": "foobar, foobar",
"traefik.tcp.routers.tcprouter0.tls.domains[1].main": "foobar",
"traefik.tcp.routers.tcprouter0.tls.domains[1].sans": "foobar, foobar",
"traefik.tcp.routers.tcprouter0.tls.options": "foobar",
"traefik.tcp.routers.tcprouter0.tls.passthrough": "true",
"traefik.tcp.routers.tcprouter1.entrypoints": "foobar, foobar",
"traefik.tcp.routers.tcprouter1.middlewares": "foobar, foobar",
"traefik.tcp.routers.tcprouter1.rule": "foobar",
"traefik.tcp.routers.tcprouter1.priority": "42",
"traefik.tcp.routers.tcprouter1.service": "foobar",
"traefik.tcp.routers.tcprouter1.tls": "true",
"traefik.tcp.routers.tcprouter1.tls.certresolver": "foobar",
"traefik.tcp.routers.tcprouter1.tls.domains[0].main": "foobar",
"traefik.tcp.routers.tcprouter1.tls.domains[0].sans": "foobar, foobar",
"traefik.tcp.routers.tcprouter1.tls.domains[1].main": "foobar",
"traefik.tcp.routers.tcprouter1.tls.domains[1].sans": "foobar, foobar",
"traefik.tcp.routers.tcprouter1.tls.options": "foobar",
"traefik.tcp.routers.tcprouter1.tls.passthrough": "true",
"traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version": "42",
"traefik.tcp.services.tcpservice01.loadbalancer.server.port": "foobar",
"traefik.tcp.services.tcpservice01.loadbalancer.server.tls": "true",
"traefik.tcp.services.tcpservice01.loadbalancer.serverstransport": "foobar",
"traefik.udp.routers.udprouter0.entrypoints": "foobar, foobar",
"traefik.udp.routers.udprouter0.service": "foobar",
"traefik.udp.routers.udprouter1.entrypoints": "foobar, foobar",
"traefik.udp.routers.udprouter1.service": "foobar",
"traefik.udp.services.udpservice01.loadbalancer.server.port": "foobar",
"traefik.tls.stores.Store0.defaultcertificate.certfile": "foobar",
"traefik.tls.stores.Store0.defaultcertificate.keyfile": "foobar",
"traefik.tls.stores.Store0.defaultgeneratedcert.domain.main": "foobar",
"traefik.tls.stores.Store0.defaultgeneratedcert.domain.sans": "foobar, foobar",
"traefik.tls.stores.Store0.defaultgeneratedcert.resolver": "foobar",
"traefik.tls.stores.Store1.defaultcertificate.certfile": "foobar",
"traefik.tls.stores.Store1.defaultcertificate.keyfile": "foobar",
"traefik.tls.stores.Store1.defaultgeneratedcert.domain.main": "foobar",
"traefik.tls.stores.Store1.defaultgeneratedcert.domain.sans": "foobar, foobar",
"traefik.tls.stores.Store1.defaultgeneratedcert.resolver": "foobar",

View file

@ -1,2 +0,0 @@
"traefik.enable": "true",
"traefik.marathon.ipaddressidx": "42",

View file

@ -1,16 +0,0 @@
---
title: "Dynamic Configuration with Marathon Labels"
description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation on the Traefik dynamic configuration with Marathon Labels."
---
# Marathon Configuration Reference
Dynamic configuration with Marathon Labels
{: .subtitle }
```json
"labels": {
--8<-- "content/reference/dynamic-configuration/marathon.json"
--8<-- "content/reference/dynamic-configuration/marathon-labels.json"
}
```

View file

@ -1,17 +0,0 @@
---
title: "Traefik Dynamic Configuration with Rancher"
description: "Read the official Traefik documentation to learn more on dynamic configuration in Traefik Proxy with Rancher Labels."
---
# Rancher Configuration Reference
Dynamic configuration with Rancher Labels
{: .subtitle }
The labels are case insensitive.
```yaml
labels:
--8<-- "content/reference/dynamic-configuration/rancher.yml"
--8<-- "content/reference/dynamic-configuration/docker-labels.yml"
```

View file

@ -1 +0,0 @@
- "traefik.enable=true"

View file

@ -288,42 +288,6 @@ Prefix to use for metrics collection. (Default: ```traefik```)
`--metrics.datadog.pushinterval`: `--metrics.datadog.pushinterval`:
Datadog push interval. (Default: ```10```) Datadog push interval. (Default: ```10```)
`--metrics.influxdb`:
InfluxDB metrics exporter type. (Default: ```false```)
`--metrics.influxdb.addentrypointslabels`:
Enable metrics on entry points. (Default: ```true```)
`--metrics.influxdb.additionallabels.<name>`:
Additional labels (influxdb tags) on all metrics
`--metrics.influxdb.address`:
InfluxDB address. (Default: ```localhost:8089```)
`--metrics.influxdb.addrouterslabels`:
Enable metrics on routers. (Default: ```false```)
`--metrics.influxdb.addserviceslabels`:
Enable metrics on services. (Default: ```true```)
`--metrics.influxdb.database`:
InfluxDB database used when protocol is http.
`--metrics.influxdb.password`:
InfluxDB password (only with http).
`--metrics.influxdb.protocol`:
InfluxDB address protocol (udp or http). (Default: ```udp```)
`--metrics.influxdb.pushinterval`:
InfluxDB push interval. (Default: ```10```)
`--metrics.influxdb.retentionpolicy`:
InfluxDB retention policy used when protocol is http.
`--metrics.influxdb.username`:
InfluxDB username (only with http).
`--metrics.influxdb2`: `--metrics.influxdb2`:
InfluxDB v2 metrics exporter type. (Default: ```false```) InfluxDB v2 metrics exporter type. (Default: ```false```)
@ -798,66 +762,6 @@ Ingress refresh throttle duration (Default: ```0```)
`--providers.kubernetesingress.token`: `--providers.kubernetesingress.token`:
Kubernetes bearer token (not needed for in-cluster client). Kubernetes bearer token (not needed for in-cluster client).
`--providers.marathon`:
Enable Marathon backend with default settings. (Default: ```false```)
`--providers.marathon.basic.httpbasicauthuser`:
Basic authentication User.
`--providers.marathon.basic.httpbasicpassword`:
Basic authentication Password.
`--providers.marathon.constraints`:
Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application.
`--providers.marathon.dcostoken`:
DCOSToken for DCOS environment, This will override the Authorization header.
`--providers.marathon.defaultrule`:
Default rule. (Default: ```Host(`{{ normalize .Name }}`)```)
`--providers.marathon.dialertimeout`:
Set a dialer timeout for Marathon. (Default: ```5```)
`--providers.marathon.endpoint`:
Marathon server endpoint. You can also specify multiple endpoint for Marathon. (Default: ```http://127.0.0.1:8080```)
`--providers.marathon.exposedbydefault`:
Expose Marathon apps by default. (Default: ```true```)
`--providers.marathon.forcetaskhostname`:
Force to use the task's hostname. (Default: ```false```)
`--providers.marathon.keepalive`:
Set a TCP Keep Alive time. (Default: ```10```)
`--providers.marathon.respectreadinesschecks`:
Filter out tasks with non-successful readiness checks during deployments. (Default: ```false```)
`--providers.marathon.responseheadertimeout`:
Set a response header timeout for Marathon. (Default: ```60```)
`--providers.marathon.tls.ca`:
TLS CA
`--providers.marathon.tls.cert`:
TLS cert
`--providers.marathon.tls.insecureskipverify`:
TLS insecure skip verify (Default: ```false```)
`--providers.marathon.tls.key`:
TLS key
`--providers.marathon.tlshandshaketimeout`:
Set a TLS handshake timeout for Marathon. (Default: ```5```)
`--providers.marathon.trace`:
Display additional provider logs. (Default: ```false```)
`--providers.marathon.watch`:
Watch provider. (Default: ```true```)
`--providers.nomad`: `--providers.nomad`:
Enable Nomad backend with default settings. (Default: ```false```) Enable Nomad backend with default settings. (Default: ```false```)
@ -912,33 +816,6 @@ Plugins configuration.
`--providers.providersthrottleduration`: `--providers.providersthrottleduration`:
Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (Default: ```2```) Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (Default: ```2```)
`--providers.rancher`:
Enable Rancher backend with default settings. (Default: ```false```)
`--providers.rancher.constraints`:
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container.
`--providers.rancher.defaultrule`:
Default rule. (Default: ```Host(`{{ normalize .Name }}`)```)
`--providers.rancher.enableservicehealthfilter`:
Filter services with unhealthy states and inactive states. (Default: ```true```)
`--providers.rancher.exposedbydefault`:
Expose containers by default. (Default: ```true```)
`--providers.rancher.intervalpoll`:
Poll the Rancher metadata service every 'rancher.refreshseconds' (less accurate). (Default: ```false```)
`--providers.rancher.prefix`:
Prefix used for accessing the Rancher metadata service. (Default: ```latest```)
`--providers.rancher.refreshseconds`:
Defines the polling interval in seconds. (Default: ```15```)
`--providers.rancher.watch`:
Watch provider. (Default: ```true```)
`--providers.redis`: `--providers.redis`:
Enable Redis backend with default settings. (Default: ```false```) Enable Redis backend with default settings. (Default: ```false```)

View file

@ -288,9 +288,6 @@ Prefix to use for metrics collection. (Default: ```traefik```)
`TRAEFIK_METRICS_DATADOG_PUSHINTERVAL`: `TRAEFIK_METRICS_DATADOG_PUSHINTERVAL`:
Datadog push interval. (Default: ```10```) Datadog push interval. (Default: ```10```)
`TRAEFIK_METRICS_INFLUXDB`:
InfluxDB metrics exporter type. (Default: ```false```)
`TRAEFIK_METRICS_INFLUXDB2`: `TRAEFIK_METRICS_INFLUXDB2`:
InfluxDB v2 metrics exporter type. (Default: ```false```) InfluxDB v2 metrics exporter type. (Default: ```false```)
@ -321,39 +318,6 @@ InfluxDB v2 push interval. (Default: ```10```)
`TRAEFIK_METRICS_INFLUXDB2_TOKEN`: `TRAEFIK_METRICS_INFLUXDB2_TOKEN`:
InfluxDB v2 access token. InfluxDB v2 access token.
`TRAEFIK_METRICS_INFLUXDB_ADDENTRYPOINTSLABELS`:
Enable metrics on entry points. (Default: ```true```)
`TRAEFIK_METRICS_INFLUXDB_ADDITIONALLABELS_<NAME>`:
Additional labels (influxdb tags) on all metrics
`TRAEFIK_METRICS_INFLUXDB_ADDRESS`:
InfluxDB address. (Default: ```localhost:8089```)
`TRAEFIK_METRICS_INFLUXDB_ADDROUTERSLABELS`:
Enable metrics on routers. (Default: ```false```)
`TRAEFIK_METRICS_INFLUXDB_ADDSERVICESLABELS`:
Enable metrics on services. (Default: ```true```)
`TRAEFIK_METRICS_INFLUXDB_DATABASE`:
InfluxDB database used when protocol is http.
`TRAEFIK_METRICS_INFLUXDB_PASSWORD`:
InfluxDB password (only with http).
`TRAEFIK_METRICS_INFLUXDB_PROTOCOL`:
InfluxDB address protocol (udp or http). (Default: ```udp```)
`TRAEFIK_METRICS_INFLUXDB_PUSHINTERVAL`:
InfluxDB push interval. (Default: ```10```)
`TRAEFIK_METRICS_INFLUXDB_RETENTIONPOLICY`:
InfluxDB retention policy used when protocol is http.
`TRAEFIK_METRICS_INFLUXDB_USERNAME`:
InfluxDB username (only with http).
`TRAEFIK_METRICS_OPENTELEMETRY`: `TRAEFIK_METRICS_OPENTELEMETRY`:
OpenTelemetry metrics exporter type. (Default: ```false```) OpenTelemetry metrics exporter type. (Default: ```false```)
@ -798,66 +762,6 @@ Ingress refresh throttle duration (Default: ```0```)
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_TOKEN`: `TRAEFIK_PROVIDERS_KUBERNETESINGRESS_TOKEN`:
Kubernetes bearer token (not needed for in-cluster client). Kubernetes bearer token (not needed for in-cluster client).
`TRAEFIK_PROVIDERS_MARATHON`:
Enable Marathon backend with default settings. (Default: ```false```)
`TRAEFIK_PROVIDERS_MARATHON_BASIC_HTTPBASICAUTHUSER`:
Basic authentication User.
`TRAEFIK_PROVIDERS_MARATHON_BASIC_HTTPBASICPASSWORD`:
Basic authentication Password.
`TRAEFIK_PROVIDERS_MARATHON_CONSTRAINTS`:
Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application.
`TRAEFIK_PROVIDERS_MARATHON_DCOSTOKEN`:
DCOSToken for DCOS environment, This will override the Authorization header.
`TRAEFIK_PROVIDERS_MARATHON_DEFAULTRULE`:
Default rule. (Default: ```Host(`{{ normalize .Name }}`)```)
`TRAEFIK_PROVIDERS_MARATHON_DIALERTIMEOUT`:
Set a dialer timeout for Marathon. (Default: ```5```)
`TRAEFIK_PROVIDERS_MARATHON_ENDPOINT`:
Marathon server endpoint. You can also specify multiple endpoint for Marathon. (Default: ```http://127.0.0.1:8080```)
`TRAEFIK_PROVIDERS_MARATHON_EXPOSEDBYDEFAULT`:
Expose Marathon apps by default. (Default: ```true```)
`TRAEFIK_PROVIDERS_MARATHON_FORCETASKHOSTNAME`:
Force to use the task's hostname. (Default: ```false```)
`TRAEFIK_PROVIDERS_MARATHON_KEEPALIVE`:
Set a TCP Keep Alive time. (Default: ```10```)
`TRAEFIK_PROVIDERS_MARATHON_RESPECTREADINESSCHECKS`:
Filter out tasks with non-successful readiness checks during deployments. (Default: ```false```)
`TRAEFIK_PROVIDERS_MARATHON_RESPONSEHEADERTIMEOUT`:
Set a response header timeout for Marathon. (Default: ```60```)
`TRAEFIK_PROVIDERS_MARATHON_TLSHANDSHAKETIMEOUT`:
Set a TLS handshake timeout for Marathon. (Default: ```5```)
`TRAEFIK_PROVIDERS_MARATHON_TLS_CA`:
TLS CA
`TRAEFIK_PROVIDERS_MARATHON_TLS_CERT`:
TLS cert
`TRAEFIK_PROVIDERS_MARATHON_TLS_INSECURESKIPVERIFY`:
TLS insecure skip verify (Default: ```false```)
`TRAEFIK_PROVIDERS_MARATHON_TLS_KEY`:
TLS key
`TRAEFIK_PROVIDERS_MARATHON_TRACE`:
Display additional provider logs. (Default: ```false```)
`TRAEFIK_PROVIDERS_MARATHON_WATCH`:
Watch provider. (Default: ```true```)
`TRAEFIK_PROVIDERS_NOMAD`: `TRAEFIK_PROVIDERS_NOMAD`:
Enable Nomad backend with default settings. (Default: ```false```) Enable Nomad backend with default settings. (Default: ```false```)
@ -912,33 +816,6 @@ Plugins configuration.
`TRAEFIK_PROVIDERS_PROVIDERSTHROTTLEDURATION`: `TRAEFIK_PROVIDERS_PROVIDERSTHROTTLEDURATION`:
Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (Default: ```2```) Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (Default: ```2```)
`TRAEFIK_PROVIDERS_RANCHER`:
Enable Rancher backend with default settings. (Default: ```false```)
`TRAEFIK_PROVIDERS_RANCHER_CONSTRAINTS`:
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container.
`TRAEFIK_PROVIDERS_RANCHER_DEFAULTRULE`:
Default rule. (Default: ```Host(`{{ normalize .Name }}`)```)
`TRAEFIK_PROVIDERS_RANCHER_ENABLESERVICEHEALTHFILTER`:
Filter services with unhealthy states and inactive states. (Default: ```true```)
`TRAEFIK_PROVIDERS_RANCHER_EXPOSEDBYDEFAULT`:
Expose containers by default. (Default: ```true```)
`TRAEFIK_PROVIDERS_RANCHER_INTERVALPOLL`:
Poll the Rancher metadata service every 'rancher.refreshseconds' (less accurate). (Default: ```false```)
`TRAEFIK_PROVIDERS_RANCHER_PREFIX`:
Prefix used for accessing the Rancher metadata service. (Default: ```latest```)
`TRAEFIK_PROVIDERS_RANCHER_REFRESHSECONDS`:
Defines the polling interval in seconds. (Default: ```15```)
`TRAEFIK_PROVIDERS_RANCHER_WATCH`:
Watch provider. (Default: ```true```)
`TRAEFIK_PROVIDERS_REDIS`: `TRAEFIK_PROVIDERS_REDIS`:
Enable Redis backend with default settings. (Default: ```false```) Enable Redis backend with default settings. (Default: ```false```)

View file

@ -98,28 +98,6 @@
watch = true watch = true
filename = "foobar" filename = "foobar"
debugLogGeneratedTemplate = true debugLogGeneratedTemplate = true
[providers.marathon]
constraints = "foobar"
trace = true
watch = true
endpoint = "foobar"
defaultRule = "foobar"
exposedByDefault = true
dcosToken = "foobar"
dialerTimeout = "42s"
responseHeaderTimeout = "42s"
tlsHandshakeTimeout = "42s"
keepAlive = "42s"
forceTaskHostname = true
respectReadinessChecks = true
[providers.marathon.tls]
ca = "foobar"
cert = "foobar"
key = "foobar"
insecureSkipVerify = true
[providers.marathon.basic]
httpBasicAuthUser = "foobar"
httpBasicPassword = "foobar"
[providers.kubernetesIngress] [providers.kubernetesIngress]
endpoint = "foobar" endpoint = "foobar"
token = "foobar" token = "foobar"
@ -154,15 +132,6 @@
throttleDuration = "42s" throttleDuration = "42s"
[providers.rest] [providers.rest]
insecure = true insecure = true
[providers.rancher]
constraints = "foobar"
watch = true
defaultRule = "foobar"
exposedByDefault = true
enableServiceHealthFilter = true
refreshSeconds = 42
intervalPoll = true
prefix = "foobar"
[providers.consulCatalog] [providers.consulCatalog]
constraints = "foobar" constraints = "foobar"
prefix = "foobar" prefix = "foobar"
@ -300,20 +269,6 @@
addRoutersLabels = true addRoutersLabels = true
addServicesLabels = true addServicesLabels = true
prefix = "foobar" prefix = "foobar"
[metrics.influxDB]
address = "foobar"
protocol = "foobar"
pushInterval = "42s"
database = "foobar"
retentionPolicy = "foobar"
username = "foobar"
password = "foobar"
addEntryPointsLabels = true
addRoutersLabels = true
addServicesLabels = true
[metrics.influxDB.additionalLabels]
name0 = "foobar"
name1 = "foobar"
[metrics.influxDB2] [metrics.influxDB2]
address = "foobar" address = "foobar"
token = "foobar" token = "foobar"

View file

@ -105,28 +105,6 @@ providers:
watch: true watch: true
filename: foobar filename: foobar
debugLogGeneratedTemplate: true debugLogGeneratedTemplate: true
marathon:
constraints: foobar
trace: true
watch: true
endpoint: foobar
defaultRule: foobar
exposedByDefault: true
dcosToken: foobar
tls:
ca: foobar
cert: foobar
key: foobar
insecureSkipVerify: true
dialerTimeout: 42s
responseHeaderTimeout: 42s
tlsHandshakeTimeout: 42s
keepAlive: 42s
forceTaskHostname: true
basic:
httpBasicAuthUser: foobar
httpBasicPassword: foobar
respectReadinessChecks: true
kubernetesIngress: kubernetesIngress:
endpoint: foobar endpoint: foobar
token: foobar token: foobar
@ -167,15 +145,6 @@ providers:
throttleDuration: 42s throttleDuration: 42s
rest: rest:
insecure: true insecure: true
rancher:
constraints: foobar
watch: true
defaultRule: foobar
exposedByDefault: true
enableServiceHealthFilter: true
refreshSeconds: 42
intervalPoll: true
prefix: foobar
consulCatalog: consulCatalog:
constraints: foobar constraints: foobar
prefix: foobar prefix: foobar
@ -329,20 +298,6 @@ metrics:
addRoutersLabels: true addRoutersLabels: true
addServicesLabels: true addServicesLabels: true
prefix: foobar prefix: foobar
influxDB:
address: foobar
protocol: foobar
pushInterval: 42s
database: foobar
retentionPolicy: foobar
username: foobar
password: foobar
addEntryPointsLabels: true
addRoutersLabels: true
addServicesLabels: true
additionalLabels:
name0: foobar
name1: foobar
influxDB2: influxDB2:
address: foobar address: foobar
token: foobar token: foobar

View file

@ -1,545 +0,0 @@
---
title: "Traefik Routing Configuration for Marathon"
description: "Traefik Proxy can be configured to use Marathon as a provider. Read the technical documentation to understand the Traefik routing configuration for Marathon."
---
# Traefik & Marathon
Traefik can be configured to use Marathon as a provider.
{: .subtitle }
See also [Marathon user guide](../../user-guides/marathon.md).
## Routing Configuration
!!! info "Labels"
- Labels are case insensitive.
- The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/marathon.md).
### General
Traefik creates, for each Marathon application, a corresponding [service](../services/index.md) and [router](../routers/index.md).
The Service automatically gets a server per instance of the application,
and the router automatically gets a rule defined by defaultRule (if no rule for it was defined in labels).
#### Service definition
--8<-- "content/routing/providers/service-by-label.md"
??? example "Automatic service assignment with labels"
Service myservice gets automatically assigned to router myproxy.
```json
labels: {
"traefik.http.routers.myproxy.rule": "Host(`example.net`)",
"traefik.http.services.myservice.loadbalancer.server.port": "80"
}
```
??? example "Automatic service creation and assignment with labels"
No service specified or defined, and yet one gets automatically created.
and assigned to router myproxy.
```json
labels: {
"traefik.http.routers.myproxy.rule": "Host(`example.net`)"
}
```
### Routers
To update the configuration of the Router automatically attached to the application,
add labels starting with `traefik.http.routers.{router-name-of-your-choice}.` and followed by the option you want to change.
For example, to change the routing rule, you could add the label ```"traefik.http.routers.routername.rule": "Host(`example.com`)"```.
!!! warning "The character `@` is not authorized in the router name `<router_name>`."
??? info "`traefik.http.routers.<router_name>.rule`"
See [rule](../routers/index.md#rule) for more information.
```json
"traefik.http.routers.myrouter.rule": "Host(`example.com`)"
```
??? info "`traefik.http.routers.<router_name>.entrypoints`"
See [entry points](../routers/index.md#entrypoints) for more information.
```json
"traefik.http.routers.myrouter.entrypoints": "ep1,ep2"
```
??? info "`traefik.http.routers.<router_name>.middlewares`"
See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information.
```json
"traefik.http.routers.myrouter.middlewares": "auth,prefix,cb"
```
??? info "`traefik.http.routers.<router_name>.service`"
See [rule](../routers/index.md#service) for more information.
```json
"traefik.http.routers.myrouter.service": "myservice"
```
??? info "`traefik.http.routers.<router_name>.tls`"
See [tls](../routers/index.md#tls) for more information.
```json
"traefik.http.routers.myrouter.tls": "true"
```
??? info "`traefik.http.routers.<router_name>.tls.certresolver`"
See [certResolver](../routers/index.md#certresolver) for more information.
```json
"traefik.http.routers.myrouter.tls.certresolver": "myresolver"
```
??? info "`traefik.http.routers.<router_name>.tls.domains[n].main`"
See [domains](../routers/index.md#domains) for more information.
```json
"traefik.http.routers.myrouter.tls.domains[0].main": "example.org"
```
??? info "`traefik.http.routers.<router_name>.tls.domains[n].sans`"
See [domains](../routers/index.md#domains) for more information.
```json
"traefik.http.routers.myrouter.tls.domains[0].sans": "test.example.org,dev.example.org"
```
??? info "`traefik.http.routers.<router_name>.tls.options`"
See [options](../routers/index.md#options) for more information.
```json
"traefik.http.routers.myrouter.tls.options": "foobar"
```
??? info "`traefik.http.routers.<router_name>.priority`"
See [priority](../routers/index.md#priority) for more information.
```json
"traefik.http.routers.myrouter.priority": "42"
```
### Services
To update the configuration of the Service automatically attached to the container,
add labels starting with `traefik.http.services.{service-name-of-your-choice}.`, followed by the option you want to change.
For example, to change the passHostHeader behavior, you'd add the label `"traefik.http.services.servicename.loadbalancer.passhostheader": "false"`.
!!! warning "The character `@` is not authorized in the service name `<service_name>`."
??? info "`traefik.http.services.<service_name>.loadbalancer.server.port`"
Registers a port.
Useful when the container exposes multiples ports.
```json
"traefik.http.services.myservice.loadbalancer.server.port": "8080"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.server.scheme`"
Overrides the default scheme.
```json
"traefik.http.services.myservice.loadbalancer.server.scheme": "http"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.serverstransport`"
Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one.
See [serverstransport](../services/index.md#serverstransport) for more information.
```json
"traefik.http.services.<service_name>.loadbalancer.serverstransport": "foobar@file"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.passhostheader`"
See [pass Host header](../services/index.md#pass-host-header) for more information.
```json
"traefik.http.services.myservice.loadbalancer.passhostheader": "true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.headers.<header_name>`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo": "foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.hostname`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.hostname": "example.org"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.interval`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.interval": "10"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.path`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.path": "/foo"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.method`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.method": "foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.status`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.status": "42"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.port`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.port": "42"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.scheme`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.scheme": "http"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.timeout`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.timeout": "10"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.followredirects`"
See [health check](../services/index.md#health-check) for more information.
```json
"traefik.http.services.myservice.loadbalancer.healthcheck.followredirects": "true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```json
"traefik.http.services.myservice.loadbalancer.sticky.cookie": "true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.httponly`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```json
"traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly": "true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.name`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```json
"traefik.http.services.myservice.loadbalancer.sticky.cookie.name": "foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```json
"traefik.http.services.myservice.loadbalancer.sticky.cookie.secure": "true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.samesite`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```json
"traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite": "none"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information.
```json
"traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval": "10"
```
### Middleware
You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{middleware-name-of-your-choice}.`, followed by the middleware type/options.
For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `"traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https"`.
More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md).
!!! warning "The character `@` is not authorized in the middleware name."
??? example "Declaring and Referencing a Middleware"
```json
{
...
"labels": {
"traefik.http.middlewares.my-redirect.redirectscheme.scheme": "https",
"traefik.http.routers.my-container.middlewares": "my-redirect"
}
}
```
!!! warning "Conflicts in Declaration"
If you declare multiple middleware with the same name but with different parameters, the middleware fails to be declared.
### TCP
You can declare TCP Routers and/or Services using labels.
??? example "Declaring TCP Routers and Services"
```json
{
...
"labels": {
"traefik.tcp.routers.my-router.rule": "HostSNI(`example.com`)",
"traefik.tcp.routers.my-router.tls": "true",
"traefik.tcp.services.my-service.loadbalancer.server.port": "4123"
}
}
```
!!! warning "TCP and HTTP"
If you declare a TCP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no TCP Router/Service is defined).
You can declare both a TCP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually).
#### TCP Routers
??? info "`traefik.tcp.routers.<router_name>.entrypoints`"
See [entry points](../routers/index.md#entrypoints_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.entrypoints": "ep1,ep2"
```
??? info "`traefik.tcp.routers.<router_name>.rule`"
See [rule](../routers/index.md#rule_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.rule": "HostSNI(`example.com`)"
```
??? info "`traefik.tcp.routers.<router_name>.service`"
See [service](../routers/index.md#services) for more information.
```json
"traefik.tcp.routers.mytcprouter.service": "myservice"
```
??? info "`traefik.tcp.routers.<router_name>.tls`"
See [TLS](../routers/index.md#tls_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.tls": "true
```
??? info "`traefik.tcp.routers.<router_name>.tls.certresolver`"
See [certResolver](../routers/index.md#certresolver_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.tls.certresolver": "myresolver"
```
??? info "`traefik.tcp.routers.<router_name>.tls.domains[n].main`"
See [domains](../routers/index.md#domains_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.tls.domains[0].main": "example.org"
```
??? info "`traefik.tcp.routers.<router_name>.tls.domains[n].sans`"
See [domains](../routers/index.md#domains_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.tls.domains[0].sans": "test.example.org,dev.example.org"
```
??? info "`traefik.tcp.routers.<router_name>.tls.options`"
See [options](../routers/index.md#options_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.tls.options": "mysoptions"
```
??? info "`traefik.tcp.routers.<router_name>.tls.passthrough`"
See [TLS](../routers/index.md#tls_1) for more information.
```json
"traefik.tcp.routers.mytcprouter.tls.passthrough": "true"
```
??? info "`traefik.tcp.routers.<router_name>.priority`"
See [priority](../routers/index.md#priority_1) for more information.
```json
"traefik.tcp.routers.myrouter.priority": "42"
```
#### TCP Services
??? info "`traefik.tcp.services.<service_name>.loadbalancer.server.port`"
Registers a port of the application.
```json
"traefik.tcp.services.mytcpservice.loadbalancer.server.port": "423"
```
??? info "`traefik.tcp.services.<service_name>.loadbalancer.server.tls`"
Determines whether to use TLS when dialing with the backend.
```json
"traefik.tcp.services.mytcpservice.loadbalancer.server.tls": "true"
```
??? info "`traefik.tcp.services.<service_name>.loadbalancer.proxyprotocol.version`"
See [PROXY protocol](../services/index.md#proxy-protocol) for more information.
```json
"traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version": "1"
```
??? info "`traefik.tcp.services.<service_name>.loadbalancer.serverstransport`"
Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one.
See [serverstransport](../services/index.md#serverstransport_2) for more information.
```json
"traefik.tcp.services.<service_name>.loadbalancer.serverstransport": "foobar@file"
```
### UDP
You can declare UDP Routers and/or Services using labels.
??? example "Declaring UDP Routers and Services"
```json
{
...
"labels": {
"traefik.udp.routers.my-router.entrypoints": "udp",
"traefik.udp.services.my-service.loadbalancer.server.port": "4123"
}
}
```
!!! warning "UDP and HTTP"
If you declare a UDP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no UDP Router/Service is defined).
You can declare both a UDP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually).
#### UDP Routers
??? info "`traefik.udp.routers.<router_name>.entrypoints`"
See [entry points](../routers/index.md#entrypoints_2) for more information.
```json
"traefik.udp.routers.myudprouter.entrypoints": "ep1,ep2"
```
??? info "`traefik.udp.routers.<router_name>.service`"
See [service](../routers/index.md#services_1) for more information.
```json
"traefik.udp.routers.myudprouter.service": "myservice"
```
#### UDP Services
??? info "`traefik.udp.services.<service_name>.loadbalancer.server.port`"
Registers a port of the application.
```json
"traefik.udp.services.myudpservice.loadbalancer.server.port": "423"
```
### Specific Provider Options
#### `traefik.enable`
```json
"traefik.enable": "true"
```
Setting this option controls whether Traefik exposes the application.
It overrides the value of `exposedByDefault`.
#### `traefik.marathon.ipadressidx`
```json
"traefik.marathon.ipadressidx": "1"
```
If a task has several IP addresses, this option specifies which one, in the list of available addresses, to select.

View file

@ -1,545 +0,0 @@
---
title: "Routing & Load Balancing Providers: Rancher"
description: "Traefik Proxy creates a corresponding service and router for each Rancher Service. Read the full documentation to learn more."
---
# Traefik & Rancher
A Story of Labels, Services & Containers
{: .subtitle }
![Rancher](../../assets/img/providers/rancher.png)
Attach labels to your services and let Traefik do the rest!
!!! important "This provider is specific to Rancher 1.x."
Rancher 2.x requires Kubernetes and does not have a metadata endpoint of its own for Traefik to query.
As such, Rancher 2.x users should utilize the [Kubernetes provider](./kubernetes-crd.md) directly.
## Routing Configuration
!!! info "Labels"
- Labels are case insensitive.
- The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/rancher.md).
### General
Traefik creates, for each rancher service, a corresponding [service](../services/index.md) and [router](../routers/index.md).
The Service automatically gets a server per container in this rancher service, and the router gets a default rule attached to it, based on the service name.
#### Service definition
--8<-- "content/routing/providers/service-by-label.md"
??? example "Automatic service assignment with labels"
With labels in a compose file
```yaml
labels:
- "traefik.http.routers.myproxy.rule=Host(`example.net`)"
# service myservice gets automatically assigned to router myproxy
- "traefik.http.services.myservice.loadbalancer.server.port=80"
```
??? example "Automatic service creation and assignment with labels"
With labels in a compose file
```yaml
labels:
# no service specified or defined and yet one gets automatically created
# and assigned to router myproxy.
- "traefik.http.routers.myproxy.rule=Host(`example.net`)"
```
### Routers
To update the configuration of the Router automatically attached to the container, add labels starting with `traefik.routers.{name-of-your-choice}.` and followed by the option you want to change.
For example, to change the rule, you could add the label ```traefik.http.routers.my-container.rule=Host(`example.com`)```.
!!! warning "The character `@` is not authorized in the router name `<router_name>`."
??? info "`traefik.http.routers.<router_name>.rule`"
See [rule](../routers/index.md#rule) for more information.
```yaml
- "traefik.http.routers.myrouter.rule=Host(`example.com`)"
```
??? info "`traefik.http.routers.<router_name>.entrypoints`"
See [entry points](../routers/index.md#entrypoints) for more information.
```yaml
- "traefik.http.routers.myrouter.entrypoints=ep1,ep2"
```
??? info "`traefik.http.routers.<router_name>.middlewares`"
See [middlewares](../routers/index.md#middlewares) and [middlewares overview](../../middlewares/overview.md) for more information.
```yaml
- "traefik.http.routers.myrouter.middlewares=auth,prefix,cb"
```
??? info "`traefik.http.routers.<router_name>.service`"
See [rule](../routers/index.md#service) for more information.
```yaml
- "traefik.http.routers.myrouter.service=myservice"
```
??? info "`traefik.http.routers.<router_name>.tls`"
See [tls](../routers/index.md#tls) for more information.
```yaml
- "traefik.http.routers.myrouter>.tls=true"
```
??? info "`traefik.http.routers.<router_name>.tls.certresolver`"
See [certResolver](../routers/index.md#certresolver) for more information.
```yaml
- "traefik.http.routers.myrouter.tls.certresolver=myresolver"
```
??? info "`traefik.http.routers.<router_name>.tls.domains[n].main`"
See [domains](../routers/index.md#domains) for more information.
```yaml
- "traefik.http.routers.myrouter.tls.domains[0].main=example.org"
```
??? info "`traefik.http.routers.<router_name>.tls.domains[n].sans`"
See [domains](../routers/index.md#domains) for more information.
```yaml
- "traefik.http.routers.myrouter.tls.domains[0].sans=test.example.org,dev.example.org"
```
??? info "`traefik.http.routers.<router_name>.tls.options`"
See [options](../routers/index.md#options) for more information.
```yaml
- "traefik.http.routers.myrouter.tls.options=foobar"
```
??? info "`traefik.http.routers.<router_name>.priority`"
See [priority](../routers/index.md#priority) for more information.
```yaml
- "traefik.http.routers.myrouter.priority=42"
```
### Services
To update the configuration of the Service automatically attached to the container,
add labels starting with `traefik.http.services.{name-of-your-choice}.`, followed by the option you want to change.
For example, to change the `passHostHeader` behavior,
you'd add the label `traefik.http.services.{name-of-your-choice}.loadbalancer.passhostheader=false`.
!!! warning "The character `@` is not authorized in the service name `<service_name>`."
??? info "`traefik.http.services.<service_name>.loadbalancer.server.port`"
Registers a port.
Useful when the container exposes multiples ports.
```yaml
- "traefik.http.services.myservice.loadbalancer.server.port=8080"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.server.scheme`"
Overrides the default scheme.
```yaml
- "traefik.http.services.myservice.loadbalancer.server.scheme=http"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.serverstransport`"
Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one.
See [serverstransport](../services/index.md#serverstransport) for more information.
```yaml
- "traefik.http.services.<service_name>.loadbalancer.serverstransport=foobar@file"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.passhostheader`"
See [pass Host header](../services/index.md#pass-host-header) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.passhostheader=true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.headers.<header_name>`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.headers.X-Foo=foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.hostname`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.hostname=example.org"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.interval`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.interval=10s"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.path`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.path=/foo"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.method`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.method=foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.status`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.status=42"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.port`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.port=42"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.scheme`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.scheme=http"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.timeout`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.timeout=10"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.healthcheck.followredirects`"
See [health check](../services/index.md#health-check) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.healthcheck.followredirects=true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie=true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.httponly`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.httponly=true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.name`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.name=foobar"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.secure`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.secure=true"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.sticky.cookie.samesite`"
See [sticky sessions](../services/index.md#sticky-sessions) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.sticky.cookie.samesite=none"
```
??? info "`traefik.http.services.<service_name>.loadbalancer.responseforwarding.flushinterval`"
See [response forwarding](../services/index.md#response-forwarding) for more information.
```yaml
- "traefik.http.services.myservice.loadbalancer.responseforwarding.flushinterval=10"
```
### Middleware
You can declare pieces of middleware using labels starting with `traefik.http.middlewares.{name-of-your-choice}.`, followed by the middleware type/options.
For example, to declare a middleware [`redirectscheme`](../../middlewares/http/redirectscheme.md) named `my-redirect`, you'd write `traefik.http.middlewares.my-redirect.redirectscheme.scheme: https`.
More information about available middlewares in the dedicated [middlewares section](../../middlewares/overview.md).
!!! warning "The character `@` is not authorized in the middleware name."
??? example "Declaring and Referencing a Middleware"
```yaml
# ...
labels:
# Declaring a middleware
- traefik.http.middlewares.my-redirect.redirectscheme.scheme=https
# Referencing a middleware
- traefik.http.routers.my-container.middlewares=my-redirect
```
!!! warning "Conflicts in Declaration"
If you declare multiple middleware with the same name but with different parameters, the middleware fails to be declared.
### TCP
You can declare TCP Routers and/or Services using labels.
??? example "Declaring TCP Routers and Services"
```yaml
services:
my-container:
# ...
labels:
- "traefik.tcp.routers.my-router.rule=HostSNI(`example.com`)"
- "traefik.tcp.routers.my-router.tls=true"
- "traefik.tcp.services.my-service.loadbalancer.server.port=4123"
```
!!! warning "TCP and HTTP"
If you declare a TCP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no TCP Router/Service is defined).
You can declare both a TCP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually).
#### TCP Routers
??? info "`traefik.tcp.routers.<router_name>.entrypoints`"
See [entry points](../routers/index.md#entrypoints_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.entrypoints=ep1,ep2"
```
??? info "`traefik.tcp.routers.<router_name>.rule`"
See [rule](../routers/index.md#rule_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.rule=HostSNI(`example.com`)"
```
??? info "`traefik.tcp.routers.<router_name>.service`"
See [service](../routers/index.md#services) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.service=myservice"
```
??? info "`traefik.tcp.routers.<router_name>.tls`"
See [TLS](../routers/index.md#tls_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.tls=true"
```
??? info "`traefik.tcp.routers.<router_name>.tls.certresolver`"
See [certResolver](../routers/index.md#certresolver_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.tls.certresolver=myresolver"
```
??? info "`traefik.tcp.routers.<router_name>.tls.domains[n].main`"
See [domains](../routers/index.md#domains_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.tls.domains[0].main=example.org"
```
??? info "`traefik.tcp.routers.<router_name>.tls.domains[n].sans`"
See [domains](../routers/index.md#domains_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.tls.domains[0].sans=test.example.org,dev.example.org"
```
??? info "`traefik.tcp.routers.<router_name>.tls.options`"
See [options](../routers/index.md#options_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.tls.options=mysoptions"
```
??? info "`traefik.tcp.routers.<router_name>.tls.passthrough`"
See [TLS](../routers/index.md#tls_1) for more information.
```yaml
- "traefik.tcp.routers.mytcprouter.tls.passthrough=true"
```
??? info "`traefik.tcp.routers.<router_name>.priority`"
See [priority](../routers/index.md#priority_1) for more information.
```yaml
- "traefik.tcp.routers.myrouter.priority=42"
```
#### TCP Services
??? info "`traefik.tcp.services.<service_name>.loadbalancer.server.port`"
Registers a port of the application.
```yaml
- "traefik.tcp.services.mytcpservice.loadbalancer.server.port=423"
```
??? info "`traefik.tcp.services.<service_name>.loadbalancer.server.tls`"
Determines whether to use TLS when dialing with the backend.
```yaml
- "traefik.tcp.services.mytcpservice.loadbalancer.server.tls=true"
```
??? info "`traefik.tcp.services.<service_name>.loadbalancer.proxyprotocol.version`"
See [PROXY protocol](../services/index.md#proxy-protocol) for more information.
```yaml
- "traefik.tcp.services.mytcpservice.loadbalancer.proxyprotocol.version=1"
```
??? info "`traefik.tcp.services.<service_name>.loadbalancer.serverstransport`"
Allows to reference a ServersTransport resource that is defined either with the File provider or the Kubernetes CRD one.
See [serverstransport](../services/index.md#serverstransport_2) for more information.
```yaml
- "traefik.tcp.services.<service_name>.loadbalancer.serverstransport=foobar@file"
```
### UDP
You can declare UDP Routers and/or Services using labels.
??? example "Declaring UDP Routers and Services"
```yaml
services:
my-container:
# ...
labels:
- "traefik.udp.routers.my-router.entrypoints=udp"
- "traefik.udp.services.my-service.loadbalancer.server.port=4123"
```
!!! warning "UDP and HTTP"
If you declare a UDP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no UDP Router/Service is defined).
You can declare both a UDP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually).
#### UDP Routers
??? info "`traefik.udp.routers.<router_name>.entrypoints`"
See [entry points](../routers/index.md#entrypoints_2) for more information.
```yaml
- "traefik.udp.routers.myudprouter.entrypoints=ep1,ep2"
```
??? info "`traefik.udp.routers.<router_name>.service`"
See [service](../routers/index.md#services_1) for more information.
```yaml
- "traefik.udp.routers.myudprouter.service=myservice"
```
#### UDP Services
??? info "`traefik.udp.services.<service_name>.loadbalancer.server.port`"
Registers a port of the application.
```yaml
- "traefik.udp.services.myudpservice.loadbalancer.server.port=423"
```
### Specific Provider Options
#### `traefik.enable`
```yaml
- "traefik.enable=true"
```
You can tell Traefik to consider (or not) the container by setting `traefik.enable` to true or false.
This option overrides the value of `exposedByDefault`.
#### Port Lookup
Traefik is capable of detecting the port to use, by following the default rancher flow.
That means, if you just expose lets say port `:1337` on the rancher ui, traefik will pick up this port and use it.

View file

@ -557,8 +557,7 @@ which is basically where the request will be passed along to.
In general, a service assigned to a router should have been defined, In general, a service assigned to a router should have been defined,
but there are exceptions for label-based providers. but there are exceptions for label-based providers.
See the specific [docker](../providers/docker.md#service-definition), [rancher](../providers/rancher.md#service-definition), See the specific [docker](../providers/docker.md#service-definition) documentation.
or [marathon](../providers/marathon.md#service-definition) documentation.
!!! warning "The character `@` is not authorized in the service name." !!! warning "The character `@` is not authorized in the service name."

View file

@ -1,133 +0,0 @@
---
title: "Traefik Proxy and Marathon Integration Guide |Traefik Docs"
description: "This guide explains how to integrate Marathon and operate the cluster in a reliable way from the Traefik Proxy standpoint."
---
# Marathon
This guide explains how to integrate Marathon and operate the cluster in a reliable way from Traefik's standpoint.
## Host detection
Marathon offers multiple ways to run (Docker-containerized) applications, the most popular ones being
- BRIDGE-networked containers with dynamic high ports exposed
- HOST-networked containers with host machine ports
- containers with dedicated IP addresses ([IP-per-task](https://mesosphere.github.io/marathon/docs/ip-per-task.html)).
Traefik tries to detect the configured mode and route traffic to the right IP addresses. It is possible to force using task hosts with the `forceTaskHostname` option.
## Port detection
Traefik also attempts to determine the right port (which is a [non-trivial matter in Marathon](https://mesosphere.github.io/marathon/docs/ports.html)) from the following sources:
1. An arbitrary port specified through label `traefik.http.services.serviceName.loadbalancer.server.port=8080`
1. The task port.
1. The port from the application's `portDefinitions` field.
1. The port from the application's `ipAddressPerTask` field.
### Port label syntax
To select a port, you can either
- specify the port directly: `traefik.http.services.serviceName.loadbalancer.server.port=8080`
- specify a port index: `traefik.http.services.serviceName.loadbalancer.server.port=index:0`
- specify a port name: `traefik.http.services.serviceName.loadbalancer.server.port=name:http`
- otherwise the first one is selected.
## Achieving high availability
### Scenarios
There are three scenarios where the availability of a Marathon application could be impaired along with the risk of losing or failing requests:
- During the startup phase when Traefik already routes requests to the backend even though it has not completed its bootstrapping process yet.
- During the shutdown phase when Traefik still routes requests to the backend while the backend is already terminating.
- During a failure of the application when Traefik has not yet identified the backend as being erroneous.
The first two scenarios are common with every rolling upgrade of an application (i.e. a new version release or configuration update).
The following sub-sections describe how to resolve or mitigate each scenario.
#### Startup
It is possible to define [readiness checks](https://mesosphere.github.io/marathon/docs/readiness-checks.html) (available since Marathon version 1.1) per application and have Marathon take these into account during the startup phase.
The idea is that each application provides an HTTP endpoint that Marathon queries periodically during an ongoing deployment in order to mark the associated readiness check result as successful if and only if the endpoint returns a response within the configured HTTP code range.
As long as the check keeps failing, Marathon will not proceed with the deployment (within the configured upgrade strategy bounds).
Beginning with version 1.4, Traefik respects readiness check results if the Traefik option is set and checks are configured on the applications accordingly.
!!! note
Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay.
It is on the order of one readiness check timeout interval (as configured on the application specification) and guarantees that non-ready tasks do not receive traffic prematurely.
If readiness checks are not possible, a current mitigation strategy is to enable [retries](../middlewares/http/retry.md) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those.
Apart from its probabilistic nature, the workaround comes at the price of increased latency.
#### Shutdown
It is possible to install a [termination handler](https://mesosphere.github.io/marathon/docs/health-checks.html) (available since Marathon version 1.3) with each application whose responsibility it is to delay the shutdown process long enough until the backend has been taken out of load-balancing rotation with reasonable confidence (i.e., Traefik has received an update from the Marathon event bus, recomputes the available Marathon backends, and applies the new configuration).
Specifically, each termination handler should install a signal handler listening for a SIGTERM signal and implement the following steps on signal reception:
1. Disable Keep-Alive HTTP connections.
1. Keep accepting HTTP requests for a certain period of time.
1. Stop accepting new connections.
1. Finish serving any in-flight requests.
1. Shut down.
Traefik already ignores Marathon tasks whose state does not match `TASK_RUNNING`; since terminating tasks transition into the `TASK_KILLING` and eventually `TASK_KILLED` state, there is nothing further that needs to be done on Traefik's end.
How long HTTP requests should continue to be accepted in step 2 depends on how long Traefik needs to receive and process the Marathon configuration update.
Under regular operational conditions, it should be on the order of seconds, with 10 seconds possibly being a good default value.
Again, configuring Traefik to do retries (as discussed in the previous section) can serve as a decent workaround strategy.
Paired with termination handlers, they would cover for those cases where either the termination sequence or Traefik cannot complete their part of the orchestration process in time.
#### Failure
A failing application always happens unexpectedly, and hence, it is very difficult or even impossible to rule out the adversal effects categorically.
Failure reasons vary broadly and could stretch from unacceptable slowness, a task crash, or a network split.
There are two mitigation efforts:
1. Configure [Marathon health checks](https://mesosphere.github.io/marathon/docs/health-checks.html) on each application.
2. Configure Traefik health checks (possibly via the `traefik.http.services.yourServiceName.loadbalancer.healthcheck.*` labels) and make sure they probe with proper frequency.
The Marathon health check makes sure that applications once deemed dysfunctional are being rescheduled to different slaves.
However, they might take a while to get triggered and the follow-up processes to complete.
For that reason, the Traefik health check provides an additional check that responds more rapidly and does not require a configuration reload to happen.
Additionally, it protects from cases that the Marathon health check may not be able to cover, such as a network split.
### (Non-)Alternatives
There are a few alternatives of varying quality that are frequently asked for.
The remaining section is going to explore them along with a benefit/cost trade-off.
#### Reusing Marathon health checks
It may seem obvious to reuse the Marathon health checks as a signal to Traefik whether an application should be taken into load-balancing rotation or not.
Apart from the increased latency a failing health check may have, a major problem with this is that Marathon does not persist the health check results.
Consequently, if a master re-election occurs in the Marathon clusters, all health check results will revert to the _unknown_ state, effectively causing all applications inside the cluster to become unavailable and leading to a complete cluster failure.
Re-elections do not only happen during regular maintenance work (often requiring rolling upgrades of the Marathon nodes) but also when the Marathon leader fails spontaneously.
As such, there is no way to handle this situation deterministically.
Finally, Marathon health checks are not mandatory (the default is to use the task state as reported by Mesos), so requiring them for Traefik would raise the entry barrier for Marathon users.
Traefik used to use the health check results as a strict requirement but moved away from it as [users reported the dramatic consequences](https://github.com/traefik/traefik/issues/653).
#### Draining
Another common approach is to let a proxy drain backends that are supposed to shut down.
That is, once a backend is supposed to shut down, Traefik would stop forwarding requests.
On the plus side, this would not require any modifications to the application in question.
However, implementing this fully within Traefik seems like a non-trivial undertaking.
Additionally, the approach is less flexible compared to a custom termination handler since only the latter allows for the implementation of custom termination sequences that go beyond simple request draining (e.g., persisting a snapshot state to disk prior to terminating).
The feature is currently not implemented; a request for draining in general is at [issue 41](https://github.com/traefik/traefik/issues/41).

View file

@ -81,8 +81,6 @@ nav:
- 'Consul Catalog': 'providers/consul-catalog.md' - 'Consul Catalog': 'providers/consul-catalog.md'
- 'Nomad': 'providers/nomad.md' - 'Nomad': 'providers/nomad.md'
- 'ECS': 'providers/ecs.md' - 'ECS': 'providers/ecs.md'
- 'Marathon': 'providers/marathon.md'
- 'Rancher': 'providers/rancher.md'
- 'File': 'providers/file.md' - 'File': 'providers/file.md'
- 'Consul': 'providers/consul.md' - 'Consul': 'providers/consul.md'
- 'Etcd': 'providers/etcd.md' - 'Etcd': 'providers/etcd.md'
@ -102,8 +100,6 @@ nav:
- 'Consul Catalog': 'routing/providers/consul-catalog.md' - 'Consul Catalog': 'routing/providers/consul-catalog.md'
- 'Nomad': 'routing/providers/nomad.md' - 'Nomad': 'routing/providers/nomad.md'
- 'ECS': 'routing/providers/ecs.md' - 'ECS': 'routing/providers/ecs.md'
- 'Marathon': 'routing/providers/marathon.md'
- 'Rancher': 'routing/providers/rancher.md'
- 'KV': 'routing/providers/kv.md' - 'KV': 'routing/providers/kv.md'
- 'HTTPS & TLS': - 'HTTPS & TLS':
- 'Overview': 'https/overview.md' - 'Overview': 'https/overview.md'
@ -155,7 +151,6 @@ nav:
- 'Metrics': - 'Metrics':
- 'Overview': 'observability/metrics/overview.md' - 'Overview': 'observability/metrics/overview.md'
- 'Datadog': 'observability/metrics/datadog.md' - 'Datadog': 'observability/metrics/datadog.md'
- 'InfluxDB': 'observability/metrics/influxdb.md'
- 'InfluxDB2': 'observability/metrics/influxdb2.md' - 'InfluxDB2': 'observability/metrics/influxdb2.md'
- 'OpenTelemetry': 'observability/metrics/opentelemetry.md' - 'OpenTelemetry': 'observability/metrics/opentelemetry.md'
- 'Prometheus': 'observability/metrics/prometheus.md' - 'Prometheus': 'observability/metrics/prometheus.md'
@ -172,7 +167,6 @@ nav:
- 'User Guides': - 'User Guides':
- 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md' - 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md'
- 'gRPC Examples': 'user-guides/grpc.md' - 'gRPC Examples': 'user-guides/grpc.md'
- 'Marathon': 'user-guides/marathon.md'
- 'Docker': - 'Docker':
- 'Basic Example': 'user-guides/docker-compose/basic-example/index.md' - 'Basic Example': 'user-guides/docker-compose/basic-example/index.md'
- 'HTTPS with Let''s Encrypt': - 'HTTPS with Let''s Encrypt':
@ -208,8 +202,6 @@ nav:
- 'Nomad': "reference/dynamic-configuration/nomad.md" - 'Nomad': "reference/dynamic-configuration/nomad.md"
- 'ECS': 'reference/dynamic-configuration/ecs.md' - 'ECS': 'reference/dynamic-configuration/ecs.md'
- 'KV': 'reference/dynamic-configuration/kv.md' - 'KV': 'reference/dynamic-configuration/kv.md'
- 'Marathon': 'reference/dynamic-configuration/marathon.md'
- 'Rancher': 'reference/dynamic-configuration/rancher.md'
- 'Deprecation Notices': - 'Deprecation Notices':
- 'Releases': 'deprecation/releases.md' - 'Releases': 'deprecation/releases.md'
- 'Features': 'deprecation/features.md' - 'Features': 'deprecation/features.md'

52
go.mod
View file

@ -9,7 +9,7 @@ require (
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000
github.com/andybalholm/brotli v1.0.4 github.com/andybalholm/brotli v1.0.4
github.com/aws/aws-sdk-go v1.44.47 github.com/aws/aws-sdk-go v1.44.47
github.com/cenkalti/backoff/v4 v4.1.3 github.com/cenkalti/backoff/v4 v4.2.0
github.com/compose-spec/compose-go v1.0.3 github.com/compose-spec/compose-go v1.0.3
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
@ -19,7 +19,6 @@ require (
github.com/docker/docker v20.10.7+incompatible github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/fatih/structs v1.1.0 github.com/fatih/structs v1.1.0
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2
github.com/go-acme/lego/v4 v4.9.1 github.com/go-acme/lego/v4 v4.9.1
github.com/go-check/check v0.0.0-00010101000000-000000000000 github.com/go-check/check v0.0.0-00010101000000-000000000000
github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea github.com/go-kit/kit v0.10.1-0.20200915143503-439c4d2ed3ea
@ -59,7 +58,6 @@ require (
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835 github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.2.0
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac
github.com/rs/zerolog v1.28.0 github.com/rs/zerolog v1.28.0
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
github.com/spiffe/go-spiffe/v2 v2.1.1 github.com/spiffe/go-spiffe/v2 v2.1.1
@ -78,24 +76,24 @@ require (
go.elastic.co/apm v1.13.1 go.elastic.co/apm v1.13.1
go.elastic.co/apm/module/apmot v1.13.1 go.elastic.co/apm/module/apmot v1.13.1
go.opentelemetry.io/collector/pdata v0.64.1 go.opentelemetry.io/collector/pdata v0.64.1
go.opentelemetry.io/otel v1.11.1 go.opentelemetry.io/otel v1.11.2
go.opentelemetry.io/otel/bridge/opentracing v1.11.1 go.opentelemetry.io/otel/bridge/opentracing v1.11.2
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.33.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.33.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2
go.opentelemetry.io/otel/metric v0.33.0 go.opentelemetry.io/otel/metric v0.34.0
go.opentelemetry.io/otel/sdk v1.11.1 go.opentelemetry.io/otel/sdk v1.11.2
go.opentelemetry.io/otel/sdk/metric v0.33.0 go.opentelemetry.io/otel/sdk/metric v0.34.0
go.opentelemetry.io/otel/trace v1.11.1 go.opentelemetry.io/otel/trace v1.11.2
golang.org/x/exp v0.0.0-20221114191408-850992195362 golang.org/x/exp v0.0.0-20221114191408-850992195362
golang.org/x/mod v0.6.0 golang.org/x/mod v0.6.0
golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 golang.org/x/net v0.4.0
golang.org/x/text v0.5.0 golang.org/x/text v0.5.0
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 golang.org/x/time v0.0.0-20220609170525-579cf78fd858
golang.org/x/tools v0.2.0 golang.org/x/tools v0.2.0
google.golang.org/grpc v1.50.1 google.golang.org/grpc v1.51.0
gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 gopkg.in/DataDog/dd-trace-go.v1 v1.43.1
gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/fsnotify.v1 v1.4.7
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@ -109,7 +107,7 @@ require (
) )
require ( require (
cloud.google.com/go v0.97.0 // indirect cloud.google.com/go/compute/metadata v0.2.0 // indirect
github.com/AlecAivazis/survey/v2 v2.2.3 // indirect github.com/AlecAivazis/survey/v2 v2.2.3 // indirect
github.com/Azure/azure-sdk-for-go v40.3.0+incompatible // indirect github.com/Azure/azure-sdk-for-go v40.3.0+incompatible // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
@ -174,7 +172,6 @@ require (
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
github.com/dustin/go-humanize v1.0.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect
github.com/elastic/go-licenser v0.3.1 // indirect github.com/elastic/go-licenser v0.3.1 // indirect
github.com/elastic/go-sysinfo v1.1.1 // indirect github.com/elastic/go-sysinfo v1.1.1 // indirect
@ -211,12 +208,13 @@ require (
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/gax-go/v2 v2.1.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.6.0 // indirect
github.com/gophercloud/gophercloud v1.0.0 // indirect github.com/gophercloud/gophercloud v1.0.0 // indirect
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0 // indirect
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
github.com/hashicorp/consul/sdk v0.10.0 // indirect github.com/hashicorp/consul/sdk v0.10.0 // indirect
github.com/hashicorp/cronexpr v1.1.1 // indirect github.com/hashicorp/cronexpr v1.1.1 // indirect
@ -347,8 +345,8 @@ require (
go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
go.etcd.io/etcd/client/v3 v3.5.4 // indirect go.etcd.io/etcd/client/v3 v3.5.4 // indirect
go.opencensus.io v0.23.0 // indirect go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.33.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
@ -358,14 +356,14 @@ require (
go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect
golang.org/x/crypto v0.1.0 // indirect golang.org/x/crypto v0.1.0 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 // indirect golang.org/x/oauth2 v0.2.0 // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect
golang.org/x/sys v0.3.0 // indirect golang.org/x/sys v0.3.0 // indirect
golang.org/x/term v0.3.0 // indirect golang.org/x/term v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.57.0 // indirect google.golang.org/api v0.100.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect gopkg.in/ini.v1 v1.66.6 // indirect

149
go.sum
View file

@ -25,23 +25,19 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute/metadata v0.2.0 h1:nBbNSZyDpkNlo3DepaaLKVuO7ClyifSAmNloSCZrHnQ=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -294,8 +290,8 @@ github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= github.com/certifi/gocertifi v0.0.0-20180118203423-deb3ae2ef261/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@ -593,8 +589,6 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNE
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e h1:rMOGp6HPeMHbdLrZkX2nD+94uqDunc27tXVuS+ey4mQ=
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@ -669,8 +663,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2 h1:df6OFl8WNXk82xxP3R9ZPZ5seOA8XZkwLdbEzZF1/xI=
github.com/gambol99/go-marathon v0.0.0-20180614232016-99a156b96fb2/go.mod h1:GLyXJD41gBO/NPKVPGQbhyyC06eugGy15QEZyUkE2/s=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
@ -851,7 +843,6 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
@ -897,7 +888,6 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -911,8 +901,6 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
@ -923,12 +911,14 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
@ -968,8 +958,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0 h1:t7uX3JBHdVwAi3G7sSSdbsk8NfgA+LnUS88V/2EKaA0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.14.0/go.mod h1:4OGVnY4qf2+gw+ssiHbW+pq4mo2yko94YxxMmXZ7jCA=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
@ -1668,8 +1659,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64= github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY= github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY=
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac h1:wBGhHdXKICZmvAPWS8gQoMyOWDH7QAi9bU4Z1nDWnFU=
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac/go.mod h1:67sLWL17mVlO1HFROaTBmU71NB4R8UNCesFHhg0f6LQ=
github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig= github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@ -1998,32 +1987,32 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/collector/pdata v0.64.1 h1:8E06uHr0nnenGftFwhwdenA88QhVnF4dJam+qVXgdVg= go.opentelemetry.io/collector/pdata v0.64.1 h1:8E06uHr0nnenGftFwhwdenA88QhVnF4dJam+qVXgdVg=
go.opentelemetry.io/collector/pdata v0.64.1/go.mod h1:IzvXUGQml2mrnvdb8zIlEW3qQs9oFLdD2hLwJdZ+pek= go.opentelemetry.io/collector/pdata v0.64.1/go.mod h1:IzvXUGQml2mrnvdb8zIlEW3qQs9oFLdD2hLwJdZ+pek=
go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4= go.opentelemetry.io/otel v1.11.2 h1:YBZcQlsVekzFsFbjygXMOXSs6pialIZxcjfO/mBDmR0=
go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE= go.opentelemetry.io/otel v1.11.2/go.mod h1:7p4EUV+AqgdlNV9gL97IgUZiVR3yrFXYo53f9BM3tRI=
go.opentelemetry.io/otel/bridge/opentracing v1.11.1 h1:/ZBsgjXWUpiZ5M9zm+Ft3kuDUGErIGcEJbKRIsFN6jA= go.opentelemetry.io/otel/bridge/opentracing v1.11.2 h1:Wx51zQDSZDNo5wxMPhkPwzgpUZLQYYDtT41LCcl7opg=
go.opentelemetry.io/otel/bridge/opentracing v1.11.1/go.mod h1:vw9hN4H+G0ek+XQtxP+Mm1McLcmdx2FXHNrWn2bBqxU= go.opentelemetry.io/otel/bridge/opentracing v1.11.2/go.mod h1:kBrIQ2vqDIqtuS7Np7ALjmm8Tml7yxgsAGQwBhNvuU0=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 h1:X2GndnMCsUPh6CiY2a+frAbNsXaPLbB0soHRYhAZ5Ig= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2 h1:htgM8vZIF8oPSCxa341e3IZ4yr/sKxgu8KZYllByiVY=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1/go.mod h1:i8vjiSzbiUC7wOQplijSXMYUpNM93DtlS5CbUT+C6oQ= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.2/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.33.0 h1:OT/UjHcjog4A1s1UMCtyehIKS+vpjM5Du0r7KGsH6TE= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0 h1:kpskzLZ60cJ48SJ4uxWa6waBL+4kSV6nVK8rP+QM8Wg=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.33.0/go.mod h1:0XctNDHEWmiSDIU8NPbJElrK05gBJFcYlGP4FMGo4g4= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.34.0/go.mod h1:4+x3i62TEegDHuzNva0bMcAN8oUi5w4liGb1d/VgPYo=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.33.0 h1:1SVtGtRsNyGgv1fRfNXfh+sJowIwzF0gkf+61lvTgdg= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0 h1:e7kFb4pJLbhJgAwUdoVTHzB9pGujs5O8/7gFyZL88fg=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.33.0/go.mod h1:ryB27ubOBXsiqfh6MwtSdx5knzbSZtjvPnMMmt3AykQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.34.0/go.mod h1:3x00m9exjIbhK+zTO4MsCSlfbVmgvLP0wjDgDKa/8bw=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.33.0 h1:NoG4v01cdLZfOeNGBQmSe4f4SeP+fx8I/0qzRgTKsGI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0 h1:t4Ajxj8JGjxkqoBtbkCOY2cDUl9RwiNE9LPQavooi9U=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.33.0/go.mod h1:6anbDXBcTp3Qit87pfFmT0paxTJ8sWRccTNYVywN/H8= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.34.0/go.mod h1:WO7omosl4P7JoanH9NgInxDxEn2F2M5YinIh8EyeT8w=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1 h1:MEQNafcNCB0uQIti/oHgU7CZpUMYQ7qigBwMVKycHvc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2 h1:fqR1kli93643au1RKo0Uma3d2aPQKT+WBKfTSBaKbOc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.1/go.mod h1:19O5I2U5iys38SsmT2uDJja/300woyzE1KPIQxEUBUc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.11.2/go.mod h1:5Qn6qvgkMsLDX+sYK64rHb1FPhpn0UtxF+ouX1uhyJE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1 h1:LYyG/f1W/jzAix16jbksJfMQFpOH/Ma6T639pVPMgfI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2 h1:ERwKPn9Aer7Gxsc0+ZlutlH1bEEAUXAUhqm3Y45ABbk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.1/go.mod h1:QrRRQiY3kzAoYPNLP0W/Ikg0gR6V3LMc+ODSxr7yyvg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.11.2/go.mod h1:jWZUM2MWhWCJ9J9xVbRx7tzK1mXKpAlze4CeulycwVY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1 h1:tFl63cpAAcD9TOU6U8kZU7KyXuSRYAZlbx1C61aaB74= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2 h1:Us8tbCmuN16zAnK5TC69AtODLycKbwnskQzaB6DfFhc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.1/go.mod h1:X620Jww3RajCJXw/unA+8IRTgxkdS7pi+ZwK9b7KUJk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.11.2/go.mod h1:GZWSQQky8AgdJj50r1KJm8oiQiIPaAX7uZCFQX9GzC8=
go.opentelemetry.io/otel/metric v0.33.0 h1:xQAyl7uGEYvrLAiV/09iTJlp1pZnQ9Wl793qbVvED1E= go.opentelemetry.io/otel/metric v0.34.0 h1:MCPoQxcg/26EuuJwpYN1mZTeCYAUGx8ABxfW07YkjP8=
go.opentelemetry.io/otel/metric v0.33.0/go.mod h1:QlTYc+EnYNq/M2mNk1qDDMRLpqCOj2f/r5c7Fd5FYaI= go.opentelemetry.io/otel/metric v0.34.0/go.mod h1:ZFuI4yQGNCupurTXCwkeD/zHBt+C2bR7bw5JqUm/AP8=
go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs= go.opentelemetry.io/otel/sdk v1.11.2 h1:GF4JoaEx7iihdMFu30sOyRx52HDHOkl9xQ8SMqNXUiU=
go.opentelemetry.io/otel/sdk v1.11.1/go.mod h1:/l3FE4SupHJ12TduVjUkZtlfFqDCQJlOlithYrdktys= go.opentelemetry.io/otel/sdk v1.11.2/go.mod h1:wZ1WxImwpq+lVRo4vsmSOxdd+xwoUJ6rqyLc3SyX9aU=
go.opentelemetry.io/otel/sdk/metric v0.33.0 h1:oTqyWfksgKoJmbrs2q7O7ahkJzt+Ipekihf8vhpa9qo= go.opentelemetry.io/otel/sdk/metric v0.34.0 h1:7ElxfQpXCFZlRTvVRTkcUvK8Gt5DC8QzmzsLsO2gdzo=
go.opentelemetry.io/otel/sdk/metric v0.33.0/go.mod h1:xdypMeA21JBOvjjzDUtD0kzIcHO/SPez+a8HOzJPGp0= go.opentelemetry.io/otel/sdk/metric v0.34.0/go.mod h1:l4r16BIqiqPy5rd14kkxllPy/fOI4tWo1jkpD9Z3ffQ=
go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ= go.opentelemetry.io/otel/trace v1.11.2 h1:Xf7hWSF2Glv0DE3MH7fBHvtpSBsjcBUe5MYAmZM/+y0=
go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk= go.opentelemetry.io/otel/trace v1.11.2/go.mod h1:4N+yC7QEz7TTsG9BSRLNAa63eg5E06ObSbKPmxQ/pKA=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
@ -2213,7 +2202,6 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -2224,8 +2212,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -2242,13 +2230,10 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA= golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -2261,8 +2246,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -2376,16 +2361,12 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -2499,8 +2480,6 @@ golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
@ -2508,8 +2487,9 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM= gonum.org/v1/gonum v0.8.2 h1:CCXrcPKiGGotvnN6jfUsKk4rRqm7q09/YbKb5xCEvtM=
@ -2544,14 +2524,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.100.0 h1:LGUYIrbW9pzYQQ8NWXlaIVkgnfubVBZbMFb9P8TK374=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0 h1:4t9zuDlHLcIx0ZEhmXEeFVCRsiOgpgn2QOH9N0MNjPI=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -2618,25 +2592,11 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
@ -2667,18 +2627,13 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

View file

@ -1,22 +0,0 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false
[log]
level = "DEBUG"
noColor = true
[entryPoints]
[entryPoints.web]
address = ":8000"
[entryPoints.traefik]
address = ":9090"
[api]
insecure = true
[providers]
[providers.marathon]
endpoint = "{{.MarathonURL}}"
watch = true
exposedByDefault = true

View file

@ -91,8 +91,6 @@ func Test(t *testing.T) {
} }
check.Suite(&KeepAliveSuite{}) check.Suite(&KeepAliveSuite{})
check.Suite(&LogRotationSuite{}) check.Suite(&LogRotationSuite{})
check.Suite(&MarathonSuite{})
check.Suite(&MarathonSuite15{})
if !useVPN { if !useVPN {
check.Suite(&ProxyProtocolSuite{}) check.Suite(&ProxyProtocolSuite{})
} }

View file

@ -1,94 +0,0 @@
package integration
import (
"net/http"
"os"
"time"
"github.com/gambol99/go-marathon"
"github.com/go-check/check"
"github.com/traefik/traefik/v2/integration/try"
checker "github.com/vdemeester/shakers"
)
// Marathon test suites.
type MarathonSuite15 struct {
BaseSuite
marathonURL string
}
func (s *MarathonSuite15) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon15")
s.composeUp(c)
s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080"
// Wait for Marathon readiness prior to creating the client so that we
// don't run into the "all cluster members down" state right from the
// start.
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}
func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
// Start Traefik.
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
MarathonURL string
}{s.marathonURL})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
// Wait for Traefik to turn ready.
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)
// Prepare Marathon client.
config := marathon.NewDefaultConfig()
config.URL = s.marathonURL
client, err := marathon.NewClient(config)
c.Assert(err, checker.IsNil)
// Create test application to be deployed.
app := marathon.NewDockerApplication().
Name("/whoami").
CPU(0.1).
Memory(32).
EmptyNetworks().
AddLabel("traefik.http.Routers.rt.Rule", "PathPrefix(`/service`)")
app.Container.
Expose(80).
Docker.
Container("traefik/whoami")
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
// Deploy the test application.
deployApplication(c, client, app)
// Query application via Traefik.
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
// Create test application with services to be deployed.
app = marathon.NewDockerApplication().
Name("/whoami").
CPU(0.1).
Memory(32).
EmptyNetworks().
AddLabel("traefik.http.Routers.app.Rule", "PathPrefix(`/app`)")
app.Container.
Expose(80).
Docker.
Container("traefik/whoami")
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
// Deploy the test application.
deployApplication(c, client, app)
// Query application via Traefik.
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}

View file

@ -1,98 +0,0 @@
package integration
import (
"net/http"
"os"
"time"
"github.com/gambol99/go-marathon"
"github.com/go-check/check"
"github.com/traefik/traefik/v2/integration/try"
checker "github.com/vdemeester/shakers"
)
const containerNameMarathon = "marathon"
// Marathon test suites.
type MarathonSuite struct {
BaseSuite
marathonURL string
}
func (s *MarathonSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "marathon")
s.composeUp(c)
s.marathonURL = "http://" + s.getComposeServiceIP(c, containerNameMarathon) + ":8080"
// Wait for Marathon readiness prior to creating the client so that we
// don't run into the "all cluster members down" state right from the
// start.
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}
func deployApplication(c *check.C, client marathon.Marathon, application *marathon.Application) {
deploy, err := client.UpdateApplication(application, false)
c.Assert(err, checker.IsNil)
// Wait for deployment to complete.
c.Assert(client.WaitOnDeployment(deploy.DeploymentID, 1*time.Minute), checker.IsNil)
}
func (s *MarathonSuite) TestConfigurationUpdate(c *check.C) {
// Start Traefik.
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
MarathonURL string
}{s.marathonURL})
defer os.Remove(file)
cmd, display := s.traefikCmd(withConfigFile(file))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer s.killCmd(cmd)
// Wait for Traefik to turn ready.
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)
// Prepare Marathon client.
config := marathon.NewDefaultConfig()
config.URL = s.marathonURL
client, err := marathon.NewClient(config)
c.Assert(err, checker.IsNil)
// Create test application to be deployed.
app := marathon.NewDockerApplication().
Name("/whoami").
CPU(0.1).
Memory(32).
AddLabel("traefik.http.Routers.rt.Rule", "PathPrefix(`/service`)")
app.Container.Docker.Bridged().
Expose(80).
Container("traefik/whoami")
// Deploy the test application.
deployApplication(c, client, app)
// Query application via Traefik.
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
// Create test application with services to be deployed.
app = marathon.NewDockerApplication().
Name("/whoami").
CPU(0.1).
Memory(32).
AddLabel("traefik.http.Routers.app.Rule", "PathPrefix(`/app`)")
app.Container.Docker.Bridged().
Expose(80).
Container("traefik/whoami")
// Deploy the test application.
deployApplication(c, client, app)
// Query application via Traefik.
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}

View file

@ -1,60 +0,0 @@
version: "3.8"
services:
zookeeper:
image: zookeeper:3.4.10
mesos-master:
image: mesosphere/mesos-master:1.0.1-2.0.93.ubuntu1404
# Uncomment published ports for interactive debugging.
# ports:
# - "5050:5050"
environment:
MESOS_HOSTNAME: mesos-master
MESOS_CLUSTER: local
MESOS_REGISTRY: in_memory
MESOS_LOG_DIR: /var/log
MESOS_WORK_DIR: /var/lib/mesos
MESOS_ZK: zk://zookeeper:2181/mesos
mesos-slave:
image: docker:dind
privileged: true
# Uncomment published ports for interactive debugging.
# ports:
# - "5051:5051"
# docker version in mesosphere/mesos-slave-dind:0.3.0_mesos-1.0.1_docker-1.10.3_ubuntu-14.04.5 is too old and can't
# pull images on new kernels.
command:
- "/bin/sh"
- "-c"
- "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \
docker -H unix:///var/run/docker.sock run -d --net=host --privileged \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /cgroup:/cgroup -v /sys:/sys \
-v /usr/local/bin/docker:/usr/local/bin/docker \
-e MESOS_HOSTNAME=$$(hostname -i) \
-e MESOS_CONTAINERIZERS=docker,mesos \
-e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \
-e MESOS_LOG_DIR=/var/log \
-e MESOS_MASTER=zk://zookeeper:2181/mesos \
-e MESOS_PORT=5051 \
-e MESOS_WORK_DIR=/var/lib/mesos \
-e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \
-e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \
-e MESOS_DOCKER_STOP_TIMEOUT=60secs \
-e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \
mesosphere/mesos-slave:1.0.3; sleep 600"
marathon:
image: mesosphere/marathon:v1.3.12
# Uncomment published ports for interactive debugging.
# ports:
# - "8080:8080"
environment:
MARATHON_ZK: zk://zookeeper:2181/marathon
MARATHON_MASTER: zk://zookeeper:2181/mesos
networks:
default:
name: traefik-test-network
external: true

View file

@ -1,59 +0,0 @@
version: "3.8"
services:
zookeeper:
image: zookeeper:3.4.10
mesos-master:
image: mesosphere/mesos-master:1.4.1
# Uncomment published ports for interactive debugging.
# ports:
# - "5050:5050"
environment:
MESOS_HOSTNAME: mesos-master
MESOS_CLUSTER: local
MESOS_REGISTRY: in_memory
MESOS_LOG_DIR: /var/log
MESOS_WORK_DIR: /var/lib/mesos
MESOS_ZK: zk://zookeeper:2181/mesos
mesos-slave:
image: docker:dind
privileged: true
# Uncomment published ports for interactive debugging.
# ports:
# - "5051:5051"
command:
- "/bin/sh"
- "-c"
- "(/usr/local/bin/dockerd-entrypoint.sh &); sleep 10; set -x; \
docker -H unix:///var/run/docker.sock run -d --net=host --privileged \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /cgroup:/cgroup -v /sys:/sys \
-v /usr/local/bin/docker:/usr/local/bin/docker \
-e MESOS_HOSTNAME=$$(hostname -i) \
-e MESOS_CONTAINERIZERS=docker,mesos \
-e MESOS_ISOLATOR=cgroups/cpu,cgroups/mem \
-e MESOS_LOG_DIR=/var/log \
-e MESOS_MASTER=zk://zookeeper:2181/mesos \
-e MESOS_PORT=5051 \
-e MESOS_WORK_DIR=/var/lib/mesos \
-e MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins \
-e MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs \
-e MESOS_DOCKER_STOP_TIMEOUT=60secs \
-e MESOS_RESOURCES='cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]' \
-e MESOS_SYSTEMD_ENABLE_SUPPORT=false \
mesosphere/mesos-slave:1.4.1; sleep 600"
marathon:
image: mesosphere/marathon:v1.5.9
# Uncomment published ports for interactive debugging.
# ports:
# - "8080:8080"
environment:
MARATHON_ZK: zk://zookeeper:2181/marathon
MARATHON_MASTER: zk://zookeeper:2181/mesos
networks:
default:
name: traefik-test-network
external: true

View file

@ -18,8 +18,6 @@ import (
"github.com/traefik/traefik/v2/pkg/provider/hub" "github.com/traefik/traefik/v2/pkg/provider/hub"
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/crd"
"github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress" "github.com/traefik/traefik/v2/pkg/provider/kubernetes/ingress"
"github.com/traefik/traefik/v2/pkg/provider/marathon"
"github.com/traefik/traefik/v2/pkg/provider/rancher"
"github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/provider/rest"
"github.com/traefik/traefik/v2/pkg/tracing/jaeger" "github.com/traefik/traefik/v2/pkg/tracing/jaeger"
"github.com/traefik/traefik/v2/pkg/types" "github.com/traefik/traefik/v2/pkg/types"
@ -238,11 +236,9 @@ func TestHandler_Overview(t *testing.T) {
Providers: &static.Providers{ Providers: &static.Providers{
Docker: &docker.Provider{}, Docker: &docker.Provider{},
File: &file.Provider{}, File: &file.Provider{},
Marathon: &marathon.Provider{},
KubernetesIngress: &ingress.Provider{}, KubernetesIngress: &ingress.Provider{},
KubernetesCRD: &crd.Provider{}, KubernetesCRD: &crd.Provider{},
Rest: &rest.Provider{}, Rest: &rest.Provider{},
Rancher: &rancher.Provider{},
Plugin: map[string]static.PluginConf{ Plugin: map[string]static.PluginConf{
"test": map[string]interface{}{}, "test": map[string]interface{}{},
}, },

View file

@ -25,11 +25,9 @@
"providers": [ "providers": [
"Docker", "Docker",
"File", "File",
"Marathon",
"KubernetesIngress", "KubernetesIngress",
"KubernetesCRD", "KubernetesCRD",
"Rest", "Rest",
"Rancher",
"plugin-test" "plugin-test"
], ],
"tcp": { "tcp": {

View file

@ -54,28 +54,6 @@
watch = true watch = true
filename = "foobar" filename = "foobar"
debugLogGeneratedTemplate = true debugLogGeneratedTemplate = true
[providers.marathon]
constraints = "foobar"
trace = true
watch = true
endpoint = "foobar"
defaultRule = "foobar"
exposedByDefault = true
dcosToken = "foobar"
dialerTimeout = 42
responseHeaderTimeout = 42
tlsHandshakeTimeout = 42
keepAlive = 42
forceTaskHostname = true
respectReadinessChecks = true
[providers.marathon.tls]
ca = "foobar"
cert = "foobar"
key = "foobar"
insecureSkipVerify = true
[providers.marathon.basic]
httpBasicAuthUser = "foobar"
httpBasicPassword = "foobar"
[providers.kubernetesIngress] [providers.kubernetesIngress]
endpoint = "foobar" endpoint = "foobar"
token = "foobar" token = "foobar"
@ -96,15 +74,6 @@
ingressClass = "foobar" ingressClass = "foobar"
[providers.rest] [providers.rest]
entryPoint = "foobar" entryPoint = "foobar"
[providers.rancher]
constraints = "foobar"
watch = true
defaultRule = "foobar"
exposedByDefault = true
enableServiceHealthFilter = true
refreshSeconds = 42
intervalPoll = true
prefix = "foobar"
[api] [api]
entryPoint = "foobar" entryPoint = "foobar"
@ -124,14 +93,6 @@
[metrics.statsD] [metrics.statsD]
address = "foobar" address = "foobar"
pushInterval = "10s" pushInterval = "10s"
[metrics.influxDB]
address = "foobar"
protocol = "foobar"
pushInterval = "10s"
database = "foobar"
retentionPolicy = "foobar"
username = "foobar"
password = "foobar"
[ping] [ping]
entryPoint = "foobar" entryPoint = "foobar"

View file

@ -25,9 +25,7 @@ import (
"github.com/traefik/traefik/v2/pkg/provider/kv/etcd" "github.com/traefik/traefik/v2/pkg/provider/kv/etcd"
"github.com/traefik/traefik/v2/pkg/provider/kv/redis" "github.com/traefik/traefik/v2/pkg/provider/kv/redis"
"github.com/traefik/traefik/v2/pkg/provider/kv/zk" "github.com/traefik/traefik/v2/pkg/provider/kv/zk"
"github.com/traefik/traefik/v2/pkg/provider/marathon"
"github.com/traefik/traefik/v2/pkg/provider/nomad" "github.com/traefik/traefik/v2/pkg/provider/nomad"
"github.com/traefik/traefik/v2/pkg/provider/rancher"
"github.com/traefik/traefik/v2/pkg/provider/rest" "github.com/traefik/traefik/v2/pkg/provider/rest"
"github.com/traefik/traefik/v2/pkg/tls" "github.com/traefik/traefik/v2/pkg/tls"
"github.com/traefik/traefik/v2/pkg/tracing/datadog" "github.com/traefik/traefik/v2/pkg/tracing/datadog"
@ -214,12 +212,10 @@ type Providers struct {
Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"` File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"`
Marathon *marathon.Provider `description:"Enable Marathon backend with default settings." json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` KubernetesGateway *gateway.Provider `description:"Enable Kubernetes gateway api provider with default settings." json:"kubernetesGateway,omitempty" toml:"kubernetesGateway,omitempty" yaml:"kubernetesGateway,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
Rest *rest.Provider `description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"` Rest *rest.Provider `description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
Rancher *rancher.Provider `description:"Enable Rancher backend with default settings." json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
ConsulCatalog *consulcatalog.ProviderBuilder `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` ConsulCatalog *consulcatalog.ProviderBuilder `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Nomad *nomad.ProviderBuilder `description:"Enable Nomad backend with default settings." json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Nomad *nomad.ProviderBuilder `description:"Enable Nomad backend with default settings." json:"nomad,omitempty" toml:"nomad,omitempty" yaml:"nomad,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
Ecs *ecs.Provider `description:"Enable AWS ECS backend with default settings." json:"ecs,omitempty" toml:"ecs,omitempty" yaml:"ecs,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` Ecs *ecs.Provider `description:"Enable AWS ECS backend with default settings." json:"ecs,omitempty" toml:"ecs,omitempty" yaml:"ecs,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
@ -278,12 +274,6 @@ func (c *Configuration) SetEffectiveConfiguration() {
} }
} }
if c.Providers.Rancher != nil {
if c.Providers.Rancher.RefreshSeconds <= 0 {
c.Providers.Rancher.RefreshSeconds = 15
}
}
// Disable Gateway API provider if not enabled in experimental. // Disable Gateway API provider if not enabled in experimental.
if c.Experimental == nil || !c.Experimental.KubernetesGateway { if c.Experimental == nil || !c.Experimental.KubernetesGateway {
c.Providers.KubernetesGateway = nil c.Providers.KubernetesGateway = nil

View file

@ -1,249 +0,0 @@
package metrics
import (
"bytes"
"context"
"fmt"
"net/url"
"regexp"
"time"
"github.com/go-kit/kit/metrics/influx"
influxdb "github.com/influxdata/influxdb1-client/v2"
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v2/pkg/logs"
"github.com/traefik/traefik/v2/pkg/safe"
"github.com/traefik/traefik/v2/pkg/types"
)
var (
influxDBClient *influx.Influx
influxDBTicker *time.Ticker
)
const (
influxDBConfigReloadsName = "traefik.config.reload.total"
influxDBConfigReloadsFailureName = influxDBConfigReloadsName + ".failure"
influxDBLastConfigReloadSuccessName = "traefik.config.reload.lastSuccessTimestamp"
influxDBLastConfigReloadFailureName = "traefik.config.reload.lastFailureTimestamp"
influxDBTLSCertsNotAfterTimestampName = "traefik.tls.certs.notAfterTimestamp"
influxDBEntryPointReqsName = "traefik.entrypoint.requests.total"
influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total"
influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration"
influxDBEntryPointOpenConnsName = "traefik.entrypoint.connections.open"
influxDBEntryPointReqsBytesName = "traefik.entrypoint.requests.bytes.total"
influxDBEntryPointRespsBytesName = "traefik.entrypoint.responses.bytes.total"
influxDBRouterReqsName = "traefik.router.requests.total"
influxDBRouterReqsTLSName = "traefik.router.requests.tls.total"
influxDBRouterReqsDurationName = "traefik.router.request.duration"
influxDBORouterOpenConnsName = "traefik.router.connections.open"
influxDBRouterReqsBytesName = "traefik.router.requests.bytes.total"
influxDBRouterRespsBytesName = "traefik.router.responses.bytes.total"
influxDBServiceReqsName = "traefik.service.requests.total"
influxDBServiceReqsTLSName = "traefik.service.requests.tls.total"
influxDBServiceReqsDurationName = "traefik.service.request.duration"
influxDBServiceRetriesTotalName = "traefik.service.retries.total"
influxDBServiceOpenConnsName = "traefik.service.connections.open"
influxDBServiceServerUpName = "traefik.service.server.up"
influxDBServiceReqsBytesName = "traefik.service.requests.bytes.total"
influxDBServiceRespsBytesName = "traefik.service.responses.bytes.total"
)
const (
protocolHTTP = "http"
protocolUDP = "udp"
)
// RegisterInfluxDB registers the metrics pusher if this didn't happen yet and creates a InfluxDB Registry instance.
func RegisterInfluxDB(ctx context.Context, config *types.InfluxDB) Registry {
if influxDBClient == nil {
influxDBClient = initInfluxDBClient(ctx, config)
}
if influxDBTicker == nil {
influxDBTicker = initInfluxDBTicker(ctx, config)
}
registry := &standardRegistry{
configReloadsCounter: influxDBClient.NewCounter(influxDBConfigReloadsName),
configReloadsFailureCounter: influxDBClient.NewCounter(influxDBConfigReloadsFailureName),
lastConfigReloadSuccessGauge: influxDBClient.NewGauge(influxDBLastConfigReloadSuccessName),
lastConfigReloadFailureGauge: influxDBClient.NewGauge(influxDBLastConfigReloadFailureName),
tlsCertsNotAfterTimestampGauge: influxDBClient.NewGauge(influxDBTLSCertsNotAfterTimestampName),
}
if config.AddEntryPointsLabels {
registry.epEnabled = config.AddEntryPointsLabels
registry.entryPointReqsCounter = influxDBClient.NewCounter(influxDBEntryPointReqsName)
registry.entryPointReqsTLSCounter = influxDBClient.NewCounter(influxDBEntryPointReqsTLSName)
registry.entryPointReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBEntryPointReqDurationName), time.Second)
registry.entryPointOpenConnsGauge = influxDBClient.NewGauge(influxDBEntryPointOpenConnsName)
registry.entryPointReqsBytesCounter = influxDBClient.NewCounter(influxDBEntryPointReqsBytesName)
registry.entryPointRespsBytesCounter = influxDBClient.NewCounter(influxDBEntryPointRespsBytesName)
}
if config.AddRoutersLabels {
registry.routerEnabled = config.AddRoutersLabels
registry.routerReqsCounter = influxDBClient.NewCounter(influxDBRouterReqsName)
registry.routerReqsTLSCounter = influxDBClient.NewCounter(influxDBRouterReqsTLSName)
registry.routerReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBRouterReqsDurationName), time.Second)
registry.routerOpenConnsGauge = influxDBClient.NewGauge(influxDBORouterOpenConnsName)
registry.routerReqsBytesCounter = influxDBClient.NewCounter(influxDBRouterReqsBytesName)
registry.routerRespsBytesCounter = influxDBClient.NewCounter(influxDBRouterRespsBytesName)
}
if config.AddServicesLabels {
registry.svcEnabled = config.AddServicesLabels
registry.serviceReqsCounter = influxDBClient.NewCounter(influxDBServiceReqsName)
registry.serviceReqsTLSCounter = influxDBClient.NewCounter(influxDBServiceReqsTLSName)
registry.serviceReqDurationHistogram, _ = NewHistogramWithScale(influxDBClient.NewHistogram(influxDBServiceReqsDurationName), time.Second)
registry.serviceRetriesCounter = influxDBClient.NewCounter(influxDBServiceRetriesTotalName)
registry.serviceOpenConnsGauge = influxDBClient.NewGauge(influxDBServiceOpenConnsName)
registry.serviceServerUpGauge = influxDBClient.NewGauge(influxDBServiceServerUpName)
registry.serviceReqsBytesCounter = influxDBClient.NewCounter(influxDBServiceReqsBytesName)
registry.serviceRespsBytesCounter = influxDBClient.NewCounter(influxDBServiceRespsBytesName)
}
return registry
}
// initInfluxDBClient creates a influxDBClient.
func initInfluxDBClient(ctx context.Context, config *types.InfluxDB) *influx.Influx {
logger := log.Ctx(ctx)
// TODO deprecated: move this switch into configuration.SetEffectiveConfiguration when web provider will be removed.
switch config.Protocol {
case protocolUDP:
if len(config.Database) > 0 || len(config.RetentionPolicy) > 0 {
logger.Warn().Msg("Database and RetentionPolicy options have no effect with UDP.")
config.Database = ""
config.RetentionPolicy = ""
}
case protocolHTTP:
if u, err := url.Parse(config.Address); err == nil {
if u.Scheme != "http" && u.Scheme != "https" {
logger.Warn().Msgf("InfluxDB address %s should specify a scheme (http or https): falling back on HTTP.", config.Address)
config.Address = "http://" + config.Address
}
} else {
logger.Error().Err(err).Msg("Unable to parse the InfluxDB address: falling back on UDP.")
config.Protocol = protocolUDP
config.Database = ""
config.RetentionPolicy = ""
}
default:
logger.Warn().Msgf("Unsupported protocol %s: falling back on UDP.", config.Protocol)
config.Protocol = protocolUDP
config.Database = ""
config.RetentionPolicy = ""
}
return influx.New(
config.AdditionalLabels,
influxdb.BatchPointsConfig{
Database: config.Database,
RetentionPolicy: config.RetentionPolicy,
},
logs.NewGoKitWrapper(*logger),
)
}
// initInfluxDBTicker initializes metrics pusher.
func initInfluxDBTicker(ctx context.Context, config *types.InfluxDB) *time.Ticker {
report := time.NewTicker(time.Duration(config.PushInterval))
safe.Go(func() {
var buf bytes.Buffer
influxDBClient.WriteLoop(ctx, report.C, &influxDBWriter{buf: buf, config: config})
})
return report
}
// StopInfluxDB stops internal influxDBTicker which controls the pushing of metrics to InfluxDB Agent and resets it to `nil`.
func StopInfluxDB() {
if influxDBTicker != nil {
influxDBTicker.Stop()
}
influxDBTicker = nil
}
type influxDBWriter struct {
buf bytes.Buffer
config *types.InfluxDB
}
// Write creates a http or udp client and attempts to write BatchPoints.
// If a "database not found" error is encountered, a CREATE DATABASE
// query is attempted when using protocol http.
func (w *influxDBWriter) Write(bp influxdb.BatchPoints) error {
c, err := w.initWriteClient()
if err != nil {
return err
}
defer c.Close()
if writeErr := c.Write(bp); writeErr != nil {
logger := log.With().Str(logs.MetricsProviderName, "influxdb").Logger()
logger.Error().Err(writeErr).Msg("Error while writing to InfluxDB")
if handleErr := w.handleWriteError(logger.WithContext(context.Background()), c, writeErr); handleErr != nil {
return handleErr
}
// Retry write after successful handling of writeErr
return c.Write(bp)
}
return nil
}
func (w *influxDBWriter) initWriteClient() (influxdb.Client, error) {
if w.config.Protocol == "http" {
return influxdb.NewHTTPClient(influxdb.HTTPConfig{
Addr: w.config.Address,
Username: w.config.Username,
Password: w.config.Password,
})
}
return influxdb.NewUDPClient(influxdb.UDPConfig{
Addr: w.config.Address,
})
}
func (w *influxDBWriter) handleWriteError(ctx context.Context, c influxdb.Client, writeErr error) error {
if w.config.Protocol != protocolHTTP {
return writeErr
}
match, matchErr := regexp.MatchString("database not found", writeErr.Error())
if matchErr != nil || !match {
return writeErr
}
qStr := fmt.Sprintf("CREATE DATABASE \"%s\"", w.config.Database)
if w.config.RetentionPolicy != "" {
qStr = fmt.Sprintf("%s WITH NAME \"%s\"", qStr, w.config.RetentionPolicy)
}
logger := log.Ctx(ctx)
logger.Debug().Msgf("InfluxDB database not found: attempting to create one with %s", qStr)
q := influxdb.NewQuery(qStr, "", "")
response, queryErr := c.Query(q)
if queryErr == nil && response.Error() != nil {
queryErr = response.Error()
}
if queryErr != nil {
logger.Error().Err(queryErr).Msg("Error while creating the InfluxDB database")
return queryErr
}
logger.Debug().Msgf("Successfully created the InfluxDB database %s", w.config.Database)
return nil
}

View file

@ -23,6 +23,38 @@ var (
influxDB2Client influxdb2.Client influxDB2Client influxdb2.Client
) )
const (
influxDBConfigReloadsName = "traefik.config.reload.total"
influxDBConfigReloadsFailureName = influxDBConfigReloadsName + ".failure"
influxDBLastConfigReloadSuccessName = "traefik.config.reload.lastSuccessTimestamp"
influxDBLastConfigReloadFailureName = "traefik.config.reload.lastFailureTimestamp"
influxDBTLSCertsNotAfterTimestampName = "traefik.tls.certs.notAfterTimestamp"
influxDBEntryPointReqsName = "traefik.entrypoint.requests.total"
influxDBEntryPointReqsTLSName = "traefik.entrypoint.requests.tls.total"
influxDBEntryPointReqDurationName = "traefik.entrypoint.request.duration"
influxDBEntryPointOpenConnsName = "traefik.entrypoint.connections.open"
influxDBEntryPointReqsBytesName = "traefik.entrypoint.requests.bytes.total"
influxDBEntryPointRespsBytesName = "traefik.entrypoint.responses.bytes.total"
influxDBRouterReqsName = "traefik.router.requests.total"
influxDBRouterReqsTLSName = "traefik.router.requests.tls.total"
influxDBRouterReqsDurationName = "traefik.router.request.duration"
influxDBORouterOpenConnsName = "traefik.router.connections.open"
influxDBRouterReqsBytesName = "traefik.router.requests.bytes.total"
influxDBRouterRespsBytesName = "traefik.router.responses.bytes.total"
influxDBServiceReqsName = "traefik.service.requests.total"
influxDBServiceReqsTLSName = "traefik.service.requests.tls.total"
influxDBServiceReqsDurationName = "traefik.service.request.duration"
influxDBServiceRetriesTotalName = "traefik.service.retries.total"
influxDBServiceOpenConnsName = "traefik.service.connections.open"
influxDBServiceServerUpName = "traefik.service.server.up"
influxDBServiceReqsBytesName = "traefik.service.requests.bytes.total"
influxDBServiceRespsBytesName = "traefik.service.responses.bytes.total"
)
// RegisterInfluxDB2 creates metrics exporter for InfluxDB2. // RegisterInfluxDB2 creates metrics exporter for InfluxDB2.
func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry { func RegisterInfluxDB2(ctx context.Context, config *types.InfluxDB2) Registry {
logger := log.Ctx(ctx) logger := log.Ctx(ctx)

View file

@ -6,6 +6,7 @@ import (
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"regexp"
"strconv" "strconv"
"testing" "testing"
"time" "time"
@ -155,3 +156,14 @@ func TestInfluxDB2(t *testing.T) {
assertMessage(t, *msgServiceOpenConns, expectedServiceOpenConns) assertMessage(t, *msgServiceOpenConns, expectedServiceOpenConns)
} }
func assertMessage(t *testing.T, msg string, patterns []string) {
t.Helper()
for _, pattern := range patterns {
re := regexp.MustCompile(pattern)
match := re.FindStringSubmatch(msg)
if len(match) != 2 {
t.Errorf("Got %q %v, want %q", msg, match, pattern)
}
}
}

View file

@ -1,267 +0,0 @@
package metrics
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"regexp"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/stvp/go-udp-testing"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v2/pkg/types"
)
func TestInfluxDB(t *testing.T) {
udp.SetAddr(":8089")
// This is needed to make sure that UDP Listener listens for data a bit longer, otherwise it will quit after a millisecond
udp.Timeout = 5 * time.Second
influxDBClient = nil
influxDBRegistry := RegisterInfluxDB(context.Background(),
&types.InfluxDB{
Address: ":8089",
PushInterval: ptypes.Duration(time.Second),
AddEntryPointsLabels: true,
AddRoutersLabels: true,
AddServicesLabels: true,
AdditionalLabels: map[string]string{"tag1": "val1"},
})
defer StopInfluxDB()
if !influxDBRegistry.IsEpEnabled() || !influxDBRegistry.IsRouterEnabled() || !influxDBRegistry.IsSvcEnabled() {
t.Fatalf("InfluxDBRegistry should return true for IsEnabled(), IsRouterEnabled() and IsSvcEnabled()")
}
expectedServer := []string{
`(traefik\.config\.reload\.total,tag1=val1 count=1) [\d]{19}`,
`(traefik\.config\.reload\.total\.failure,tag1=val1 count=1) [\d]{19}`,
`(traefik\.config\.reload\.lastSuccessTimestamp,tag1=val1 value=1) [\d]{19}`,
`(traefik\.config\.reload\.lastFailureTimestamp,tag1=val1 value=1) [\d]{19}`,
}
msgServer := udp.ReceiveString(t, func() {
influxDBRegistry.ConfigReloadsCounter().Add(1)
influxDBRegistry.ConfigReloadsFailureCounter().Add(1)
influxDBRegistry.LastConfigReloadSuccessGauge().Set(1)
influxDBRegistry.LastConfigReloadFailureGauge().Set(1)
})
assertMessage(t, msgServer, expectedServer)
expectedTLS := []string{
`(traefik\.tls\.certs\.notAfterTimestamp,key=value,tag1=val1 value=1) [\d]{19}`,
}
msgTLS := udp.ReceiveString(t, func() {
influxDBRegistry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1)
})
assertMessage(t, msgTLS, expectedTLS)
expectedEntrypoint := []string{
`(traefik\.entrypoint\.requests\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`,
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
`(traefik\.entrypoint\.connections\.open,entrypoint=test,tag1=val1 value=1) [\d]{19}`,
`(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`,
`(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET,tag1=val1 count=1) [\d]{19}`,
}
msgEntrypoint := udp.ReceiveString(t, func() {
influxDBRegistry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
influxDBRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
})
assertMessage(t, msgEntrypoint, expectedEntrypoint)
expectedRouter := []string{
`(traefik\.router\.requests\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`,
`(traefik\.router\.requests\.total,code=404,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`,
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
`(traefik\.router\.request\.duration,code=200,router=demo,service=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
`(traefik\.router\.connections\.open,router=demo,service=test,tag1=val1 value=1) [\d]{19}`,
`(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`,
`(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test,tag1=val1 count=1) [\d]{19}`,
}
msgRouter := udp.ReceiveString(t, func() {
influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
influxDBRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
})
assertMessage(t, msgRouter, expectedRouter)
expectedService := []string{
`(traefik\.service\.requests\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`,
`(traefik\.service\.requests\.total,code=404,method=GET,service=test,tag1=val1 count=1) [\d]{19}`,
`(traefik\.service\.requests\.tls\.total,service=test,tag1=val1,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
`(traefik\.service\.request\.duration,code=200,service=test,tag1=val1 p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
`(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test,tag1=val1 count=2) [\d]{19}`,
`(traefik\.service\.server\.up,service=test,tag1=val1,url=http://127.0.0.1 value=1) [\d]{19}`,
`(traefik\.service\.connections\.open,service=test,tag1=val1 value=1) [\d]{19}`,
`(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`,
`(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test,tag1=val1 count=1) [\d]{19}`,
}
msgService := udp.ReceiveString(t, func() {
influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
influxDBRegistry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
influxDBRegistry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
influxDBRegistry.ServiceOpenConnsGauge().With("service", "test").Set(1)
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
influxDBRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
})
assertMessage(t, msgService, expectedService)
}
func TestInfluxDBHTTP(t *testing.T) {
c := make(chan *string)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, err := io.ReadAll(r.Body)
require.NoError(t, err)
bodyStr := string(body)
c <- &bodyStr
_, _ = fmt.Fprintln(w, "ok")
}))
defer ts.Close()
influxDBClient = nil
influxDBRegistry := RegisterInfluxDB(context.Background(),
&types.InfluxDB{
Address: ts.URL,
Protocol: "http",
PushInterval: ptypes.Duration(10 * time.Millisecond),
Database: "test",
RetentionPolicy: "autogen",
AddEntryPointsLabels: true,
AddServicesLabels: true,
AddRoutersLabels: true,
})
defer StopInfluxDB()
if !influxDBRegistry.IsEpEnabled() || !influxDBRegistry.IsRouterEnabled() || !influxDBRegistry.IsSvcEnabled() {
t.Fatalf("InfluxDB registry must be epEnabled")
}
expectedServer := []string{
`(traefik\.config\.reload\.total count=1) [\d]{19}`,
`(traefik\.config\.reload\.total\.failure count=1) [\d]{19}`,
`(traefik\.config\.reload\.lastSuccessTimestamp value=1) [\d]{19}`,
`(traefik\.config\.reload\.lastFailureTimestamp value=1) [\d]{19}`,
}
influxDBRegistry.ConfigReloadsCounter().Add(1)
influxDBRegistry.ConfigReloadsFailureCounter().Add(1)
influxDBRegistry.LastConfigReloadSuccessGauge().Set(1)
influxDBRegistry.LastConfigReloadFailureGauge().Set(1)
msgServer := <-c
assertMessage(t, *msgServer, expectedServer)
expectedTLS := []string{
`(traefik\.tls\.certs\.notAfterTimestamp,key=value value=1) [\d]{19}`,
}
influxDBRegistry.TLSCertsNotAfterTimestampGauge().With("key", "value").Set(1)
msgTLS := <-c
assertMessage(t, *msgTLS, expectedTLS)
expectedEntrypoint := []string{
`(traefik\.entrypoint\.requests\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
`(traefik\.entrypoint\.requests\.tls\.total,entrypoint=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
`(traefik\.entrypoint\.request\.duration(?:,code=[\d]{3})?,entrypoint=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
`(traefik\.entrypoint\.connections\.open,entrypoint=test value=1) [\d]{19}`,
`(traefik\.entrypoint\.requests\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
`(traefik\.entrypoint\.responses\.bytes\.total,code=200,entrypoint=test,method=GET count=1) [\d]{19}`,
}
influxDBRegistry.EntryPointReqsCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.EntryPointReqsTLSCounter().With("entrypoint", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
influxDBRegistry.EntryPointReqDurationHistogram().With("entrypoint", "test").Observe(10000)
influxDBRegistry.EntryPointOpenConnsGauge().With("entrypoint", "test").Set(1)
influxDBRegistry.EntryPointReqsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.EntryPointRespsBytesCounter().With("entrypoint", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
msgEntrypoint := <-c
assertMessage(t, *msgEntrypoint, expectedEntrypoint)
expectedRouter := []string{
`(traefik\.router\.requests\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
`(traefik\.router\.requests\.total,code=404,method=GET,router=demo,service=test count=1) [\d]{19}`,
`(traefik\.router\.requests\.tls\.total,router=demo,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
`(traefik\.router\.request\.duration,code=200,router=demo,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
`(traefik\.router\.connections\.open,router=demo,service=test value=1) [\d]{19}`,
`(traefik\.router\.requests\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
`(traefik\.router\.responses\.bytes\.total,code=200,method=GET,router=demo,service=test count=1) [\d]{19}`,
}
influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
influxDBRegistry.RouterReqsCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.RouterReqsTLSCounter().With("router", "demo", "service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
influxDBRegistry.RouterReqDurationHistogram().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
influxDBRegistry.RouterOpenConnsGauge().With("router", "demo", "service", "test").Set(1)
influxDBRegistry.RouterReqsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.RouterRespsBytesCounter().With("router", "demo", "service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
msgRouter := <-c
assertMessage(t, *msgRouter, expectedRouter)
expectedService := []string{
`(traefik\.service\.requests\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
`(traefik\.service\.requests\.total,code=404,method=GET,service=test count=1) [\d]{19}`,
`(traefik\.service\.requests\.tls\.total,service=test,tls_cipher=bar,tls_version=foo count=1) [\d]{19}`,
`(traefik\.service\.request\.duration,code=200,service=test p50=10000,p90=10000,p95=10000,p99=10000) [\d]{19}`,
`(traefik\.service\.retries\.total(?:,code=[\d]{3},method=GET)?,service=test count=2) [\d]{19}`,
`(traefik\.service\.server\.up,service=test,url=http://127.0.0.1 value=1) [\d]{19}`,
`(traefik\.service\.connections\.open,service=test value=1) [\d]{19}`,
`(traefik\.service\.requests\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
`(traefik\.service\.responses\.bytes\.total,code=200,method=GET,service=test count=1) [\d]{19}`,
}
influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.ServiceReqsCounter().With("service", "test", "code", strconv.Itoa(http.StatusNotFound), "method", http.MethodGet).Add(1)
influxDBRegistry.ServiceReqsTLSCounter().With("service", "test", "tls_version", "foo", "tls_cipher", "bar").Add(1)
influxDBRegistry.ServiceReqDurationHistogram().With("service", "test", "code", strconv.Itoa(http.StatusOK)).Observe(10000)
influxDBRegistry.ServiceOpenConnsGauge().With("service", "test").Set(1)
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
influxDBRegistry.ServiceRetriesCounter().With("service", "test").Add(1)
influxDBRegistry.ServiceServerUpGauge().With("service", "test", "url", "http://127.0.0.1").Set(1)
influxDBRegistry.ServiceReqsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
influxDBRegistry.ServiceRespsBytesCounter().With("service", "test", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet).Add(1)
msgService := <-c
assertMessage(t, *msgService, expectedService)
}
func assertMessage(t *testing.T, msg string, patterns []string) {
t.Helper()
for _, pattern := range patterns {
re := regexp.MustCompile(pattern)
match := re.FindStringSubmatch(msg)
if len(match) != 2 {
t.Errorf("Got %q %v, want %q", msg, match, pattern)
}
}
}

View file

@ -23,7 +23,6 @@ import (
"go.opentelemetry.io/otel/metric/unit" "go.opentelemetry.io/otel/metric/unit"
sdkmetric "go.opentelemetry.io/otel/sdk/metric" sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/aggregation" "go.opentelemetry.io/otel/sdk/metric/aggregation"
"go.opentelemetry.io/otel/sdk/metric/view"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"google.golang.org/grpc/encoding/gzip" "google.golang.org/grpc/encoding/gzip"
) )
@ -144,23 +143,16 @@ func newOpenTelemetryMeterProvider(ctx context.Context, config *types.OpenTeleme
sdkmetric.WithInterval(time.Duration(config.PushInterval)), sdkmetric.WithInterval(time.Duration(config.PushInterval)),
} }
meterProvider := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter, opts...)),
// View to customize histogram buckets and rename a single histogram instrument. // View to customize histogram buckets and rename a single histogram instrument.
customBucketsView, err := view.New( sdkmetric.WithView(sdkmetric.NewView(
// Match* to match instruments sdkmetric.Instrument{Name: "traefik_*_request_duration_seconds"},
view.MatchInstrumentName("traefik_*_request_duration_seconds"), sdkmetric.Stream{Aggregation: aggregation.ExplicitBucketHistogram{
view.WithSetAggregation(aggregation.ExplicitBucketHistogram{
Boundaries: config.ExplicitBoundaries, Boundaries: config.ExplicitBoundaries,
}), }},
)),
) )
if err != nil {
return nil, fmt.Errorf("creating histogram view: %w", err)
}
meterProvider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(
sdkmetric.NewPeriodicReader(exporter, opts...),
customBucketsView,
))
global.SetMeterProvider(meterProvider) global.SetMeterProvider(meterProvider)

View file

@ -80,10 +80,6 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator {
p.quietAddProvider(conf.Docker) p.quietAddProvider(conf.Docker)
} }
if conf.Marathon != nil {
p.quietAddProvider(conf.Marathon)
}
if conf.Rest != nil { if conf.Rest != nil {
p.quietAddProvider(conf.Rest) p.quietAddProvider(conf.Rest)
} }
@ -100,10 +96,6 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator {
p.quietAddProvider(conf.KubernetesGateway) p.quietAddProvider(conf.KubernetesGateway)
} }
if conf.Rancher != nil {
p.quietAddProvider(conf.Rancher)
}
if conf.Ecs != nil { if conf.Ecs != nil {
p.quietAddProvider(conf.Ecs) p.quietAddProvider(conf.Ecs)
} }

View file

@ -3,22 +3,16 @@ package constraints
import ( import (
"errors" "errors"
"regexp" "regexp"
"strings"
"github.com/vulcand/predicate" "github.com/vulcand/predicate"
) )
// MarathonConstraintPrefix is the prefix for each label's key created from a Marathon application constraint.
// It is used in order to create a specific and unique pattern for these labels.
const MarathonConstraintPrefix = "Traefik-Marathon-505F9E15-BDC7-45E7-828D-C06C7BAB8091"
type constraintLabelFunc func(map[string]string) bool type constraintLabelFunc func(map[string]string) bool
// MatchLabels reports whether the expression matches with the given labels. // MatchLabels reports whether the expression matches with the given labels.
// The expression must match any logical boolean combination of: // The expression must match any logical boolean combination of:
// - `Label(labelName, labelValue)` // - `Label(labelName, labelValue)`
// - `LabelRegex(labelName, regexValue)` // - `LabelRegex(labelName, regexValue)`.
// - `MarathonConstraint(field:operator:value)`.
func MatchLabels(labels map[string]string, expr string) (bool, error) { func MatchLabels(labels map[string]string, expr string) (bool, error) {
if expr == "" { if expr == "" {
return true, nil return true, nil
@ -33,7 +27,6 @@ func MatchLabels(labels map[string]string, expr string) (bool, error) {
Functions: map[string]interface{}{ Functions: map[string]interface{}{
"Label": labelFn, "Label": labelFn,
"LabelRegex": labelRegexFn, "LabelRegex": labelRegexFn,
"MarathonConstraint": marathonFn,
}, },
}) })
if err != nil { if err != nil {
@ -68,19 +61,6 @@ func labelRegexFn(name, expr string) constraintLabelFunc {
} }
} }
func marathonFn(value string) constraintLabelFunc {
return func(labels map[string]string) bool {
for k, v := range labels {
if strings.HasPrefix(k, MarathonConstraintPrefix) {
if v == value {
return true
}
}
}
return false
}
}
func andLabelFunc(a, b constraintLabelFunc) constraintLabelFunc { func andLabelFunc(a, b constraintLabelFunc) constraintLabelFunc {
return func(labels map[string]string) bool { return func(labels map[string]string) bool {
return a(labels) && b(labels) return a(labels) && b(labels)

View file

@ -118,33 +118,6 @@ func TestMatchLabels(t *testing.T) {
expr: ``, expr: ``,
expected: true, expected: true,
}, },
{
expr: `MarathonConstraint("bar")`,
labels: map[string]string{
"hello": "world",
MarathonConstraintPrefix + "-1": "bar",
MarathonConstraintPrefix + "-2": "foo",
},
expected: true,
},
{
expr: `MarathonConstraint("bur")`,
labels: map[string]string{
"hello": "world",
MarathonConstraintPrefix + "-1": "bar",
MarathonConstraintPrefix + "-2": "foo",
},
expected: false,
},
{
expr: `Label("hello", "world") && MarathonConstraint("bar")`,
labels: map[string]string{
"hello": "world",
MarathonConstraintPrefix + "-1": "bar",
MarathonConstraintPrefix + "-2": "foo",
},
expected: true,
},
{ {
expr: `LabelRegex("hello", "w\\w+")`, expr: `LabelRegex("hello", "w\\w+")`,
labels: map[string]string{ labels: map[string]string{

View file

@ -39,7 +39,7 @@ spec:
kind: Gateway kind: Gateway
group: gateway.networking.k8s.io group: gateway.networking.k8s.io
hostnames: hostnames:
- "*.foo.bar" - "*.foo.*.bar"
rules: rules:
- backendRefs: - backendRefs:
- name: whoamitcp - name: whoamitcp

View file

@ -839,7 +839,7 @@ func gatewayTCPRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
} }
router := dynamic.TCPRouter{ router := dynamic.TCPRouter{
Rule: "HostSNI(`*`)", // Gateway listener hostname not available in TCP Rule: "HostSNI(`*`)",
EntryPoints: []string{ep}, EntryPoints: []string{ep},
} }
@ -970,8 +970,16 @@ func gatewayTLSRouteToTCPConf(ctx context.Context, ep string, listener v1alpha2.
hostnames := matchingHostnames(listener, route.Spec.Hostnames) hostnames := matchingHostnames(listener, route.Spec.Hostnames)
if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 { if len(hostnames) == 0 && listener.Hostname != nil && *listener.Hostname != "" && len(route.Spec.Hostnames) > 0 {
// TODO update the corresponding route parent status for _, parent := range route.Status.Parents {
// https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.TLSRoute parent.Conditions = append(parent.Conditions, metav1.Condition{
Type: string(v1alpha2.GatewayClassConditionStatusAccepted),
Status: metav1.ConditionFalse,
Reason: string(v1alpha2.ListenerReasonRouteConflict),
Message: fmt.Sprintf("No hostname match between listener: %v and route: %v", listener.Hostname, route.Spec.Hostnames),
LastTransitionTime: metav1.Now(),
})
}
continue continue
} }
@ -1207,7 +1215,7 @@ func hostRule(hostnames []v1alpha2.Hostname) (string, error) {
} }
func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) { func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) {
var matchers []string rules := make([]string, 0, len(hostnames))
uniqHostnames := map[v1alpha2.Hostname]struct{}{} uniqHostnames := map[v1alpha2.Hostname]struct{}{}
for _, hostname := range hostnames { for _, hostname := range hostnames {
@ -1219,25 +1227,28 @@ func hostSNIRule(hostnames []v1alpha2.Hostname) (string, error) {
continue continue
} }
h := string(hostname) host := string(hostname)
// TODO support wildcard hostnames with an HostSNI regexp matcher
if strings.Contains(h, "*") {
return "", fmt.Errorf("wildcard hostname is not supported: %q", h)
}
matchers = append(matchers, fmt.Sprintf("HostSNI(`%s`)", h))
uniqHostnames[hostname] = struct{}{} uniqHostnames[hostname] = struct{}{}
wildcard := strings.Count(host, "*")
if wildcard == 0 {
rules = append(rules, fmt.Sprintf("HostSNI(`%s`)", host))
continue
} }
switch len(matchers) { if !strings.HasPrefix(host, "*.") || wildcard > 1 {
case 0: return "", fmt.Errorf("invalid rule: %q", host)
return "HostSNI(`*`)", nil
case 1:
return matchers[0], nil
default:
return fmt.Sprintf("(%s)", strings.Join(matchers, " || ")), nil
} }
host = strings.Replace(regexp.QuoteMeta(host), `\*\.`, `[a-zA-Z0-9-]+\.`, 1)
rules = append(rules, fmt.Sprintf("HostSNIRegexp(`^%s$`)", host))
}
if len(hostnames) == 0 || len(rules) == 0 {
return "HostSNI(`*`)", nil
}
return strings.Join(rules, " || "), nil
} }
func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, error) { func extractRule(routeRule v1alpha2.HTTPRouteRule, hostRule string) (string, error) {

View file

@ -3076,10 +3076,10 @@ func TestLoadTLSRoutes(t *testing.T) {
}, },
TCP: &dynamic.TCPConfiguration{ TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{ Routers: map[string]*dynamic.TCPRouter{
"default-tls-app-1-my-gateway-tls-dfc5c7506ac1b172c8b7": { "default-tls-app-1-my-gateway-tls-d5342d75658583f03593": {
EntryPoints: []string{"tls"}, EntryPoints: []string{"tls"},
Service: "default-tls-app-1-my-gateway-tls-dfc5c7506ac1b172c8b7-wrr-0", Service: "default-tls-app-1-my-gateway-tls-d5342d75658583f03593-wrr-0",
Rule: "(HostSNI(`foo.example.com`) || HostSNI(`bar.example.com`))", Rule: "HostSNI(`foo.example.com`) || HostSNI(`bar.example.com`)",
TLS: &dynamic.RouterTCPTLSConfig{ TLS: &dynamic.RouterTCPTLSConfig{
Passthrough: true, Passthrough: true,
}, },
@ -3087,7 +3087,7 @@ func TestLoadTLSRoutes(t *testing.T) {
}, },
Middlewares: map[string]*dynamic.TCPMiddleware{}, Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{ Services: map[string]*dynamic.TCPService{
"default-tls-app-1-my-gateway-tls-dfc5c7506ac1b172c8b7-wrr-0": { "default-tls-app-1-my-gateway-tls-d5342d75658583f03593-wrr-0": {
Weighted: &dynamic.TCPWeightedRoundRobin{ Weighted: &dynamic.TCPWeightedRoundRobin{
Services: []dynamic.TCPWRRService{ Services: []dynamic.TCPWRRService{
{ {
@ -4780,6 +4780,11 @@ func Test_hostSNIRule(t *testing.T) {
hostnames: []v1alpha2.Hostname{"*"}, hostnames: []v1alpha2.Hostname{"*"},
expectError: true, expectError: true,
}, },
{
desc: "Supported wildcard",
hostnames: []v1alpha2.Hostname{"*.foo"},
expectedRule: "HostSNIRegexp(`^[a-zA-Z0-9-]+\\.foo$`)",
},
{ {
desc: "Multiple malformed wildcard", desc: "Multiple malformed wildcard",
hostnames: []v1alpha2.Hostname{"*.foo.*"}, hostnames: []v1alpha2.Hostname{"*.foo.*"},
@ -4788,7 +4793,7 @@ func Test_hostSNIRule(t *testing.T) {
{ {
desc: "Some empty hostnames", desc: "Some empty hostnames",
hostnames: []v1alpha2.Hostname{"foo", "", "bar"}, hostnames: []v1alpha2.Hostname{"foo", "", "bar"},
expectedRule: "(HostSNI(`foo`) || HostSNI(`bar`))", expectedRule: "HostSNI(`foo`) || HostSNI(`bar`)",
}, },
{ {
desc: "Valid hostname", desc: "Valid hostname",
@ -4798,12 +4803,17 @@ func Test_hostSNIRule(t *testing.T) {
{ {
desc: "Multiple valid hostnames", desc: "Multiple valid hostnames",
hostnames: []v1alpha2.Hostname{"foo", "bar"}, hostnames: []v1alpha2.Hostname{"foo", "bar"},
expectedRule: "(HostSNI(`foo`) || HostSNI(`bar`))", expectedRule: "HostSNI(`foo`) || HostSNI(`bar`)",
},
{
desc: "Multiple valid hostnames with wildcard",
hostnames: []v1alpha2.Hostname{"bar.foo", "foo.foo", "*.foo"},
expectedRule: "HostSNI(`bar.foo`) || HostSNI(`foo.foo`) || HostSNIRegexp(`^[a-zA-Z0-9-]+\\.foo$`)",
}, },
{ {
desc: "Multiple overlapping hostnames", desc: "Multiple overlapping hostnames",
hostnames: []v1alpha2.Hostname{"foo", "bar", "foo", "baz"}, hostnames: []v1alpha2.Hostname{"foo", "bar", "foo", "baz"},
expectedRule: "(HostSNI(`foo`) || HostSNI(`bar`) || HostSNI(`baz`))", expectedRule: "HostSNI(`foo`) || HostSNI(`bar`) || HostSNI(`baz`)",
}, },
} }

View file

@ -1,205 +0,0 @@
package marathon
import (
"strings"
"time"
"github.com/gambol99/go-marathon"
)
const testTaskName = "taskID"
// Functions related to building applications.
func withApplications(apps ...marathon.Application) *marathon.Applications {
return &marathon.Applications{Apps: apps}
}
func application(ops ...func(*marathon.Application)) marathon.Application {
app := marathon.Application{}
app.EmptyLabels()
app.Deployments = []map[string]string{}
app.ReadinessChecks = &[]marathon.ReadinessCheck{}
app.ReadinessCheckResults = &[]marathon.ReadinessCheckResult{}
for _, op := range ops {
op(&app)
}
return app
}
func appID(name string) func(*marathon.Application) {
return func(app *marathon.Application) {
app.Name(name)
}
}
func appPorts(ports ...int) func(*marathon.Application) {
return func(app *marathon.Application) {
app.Ports = append(app.Ports, ports...)
}
}
func withLabel(key, value string) func(*marathon.Application) {
return func(app *marathon.Application) {
app.AddLabel(key, value)
}
}
func constraint(value string) func(*marathon.Application) {
return func(app *marathon.Application) {
app.AddConstraint(strings.Split(value, ":")...)
}
}
func portDefinition(port int, name string) func(*marathon.Application) {
return func(app *marathon.Application) {
app.AddPortDefinition(marathon.PortDefinition{
Port: &port,
Name: name,
})
}
}
func bridgeNetwork() func(*marathon.Application) {
return func(app *marathon.Application) {
app.SetNetwork("bridge", marathon.BridgeNetworkMode)
}
}
func containerNetwork() func(*marathon.Application) {
return func(app *marathon.Application) {
app.SetNetwork("cni", marathon.ContainerNetworkMode)
}
}
func ipAddrPerTask(port int) func(*marathon.Application) {
return func(app *marathon.Application) {
p := marathon.Port{
Number: port,
Name: "port",
}
disc := marathon.Discovery{}
disc.AddPort(p)
ipAddr := marathon.IPAddressPerTask{}
ipAddr.SetDiscovery(disc)
app.SetIPAddressPerTask(ipAddr)
}
}
func deployments(ids ...string) func(*marathon.Application) {
return func(app *marathon.Application) {
for _, id := range ids {
app.Deployments = append(app.Deployments, map[string]string{
"ID": id,
})
}
}
}
func readinessCheck(timeout time.Duration) func(*marathon.Application) {
return func(app *marathon.Application) {
app.ReadinessChecks = &[]marathon.ReadinessCheck{
{
Path: "/ready",
TimeoutSeconds: int(timeout.Seconds()),
},
}
}
}
func readinessCheckResult(taskID string, ready bool) func(*marathon.Application) {
return func(app *marathon.Application) {
*app.ReadinessCheckResults = append(*app.ReadinessCheckResults, marathon.ReadinessCheckResult{
TaskID: taskID,
Ready: ready,
})
}
}
func withTasks(tasks ...marathon.Task) func(*marathon.Application) {
return func(application *marathon.Application) {
for _, task := range tasks {
tu := task
application.Tasks = append(application.Tasks, &tu)
}
}
}
// Functions related to building tasks.
func task(ops ...func(*marathon.Task)) marathon.Task {
t := &marathon.Task{
ID: testTaskName,
// The vast majority of tests expect the task state to be TASK_RUNNING.
State: string(taskStateRunning),
}
for _, op := range ops {
op(t)
}
return *t
}
func withTaskID(id string) func(*marathon.Task) {
return func(task *marathon.Task) {
task.ID = id
}
}
func localhostTask(ops ...func(*marathon.Task)) marathon.Task {
t := task(
host("localhost"),
ipAddresses("127.0.0.1"),
taskState(taskStateRunning),
)
for _, op := range ops {
op(&t)
}
return t
}
func taskPorts(ports ...int) func(*marathon.Task) {
return func(t *marathon.Task) {
t.Ports = append(t.Ports, ports...)
}
}
func taskState(state TaskState) func(*marathon.Task) {
return func(t *marathon.Task) {
t.State = string(state)
}
}
func host(h string) func(*marathon.Task) {
return func(t *marathon.Task) {
t.Host = h
}
}
func ipAddresses(addresses ...string) func(*marathon.Task) {
return func(t *marathon.Task) {
for _, addr := range addresses {
t.IPAddresses = append(t.IPAddresses, &marathon.IPAddress{
IPAddress: addr,
Protocol: "tcp",
})
}
}
}
func startedAt(timestamp string) func(*marathon.Task) {
return func(t *marathon.Task) {
t.StartedAt = timestamp
}
}
func startedAtFromNow(offset time.Duration) func(*marathon.Task) {
return func(t *marathon.Task) {
t.StartedAt = time.Now().Add(-offset).Format(time.RFC3339)
}
}

View file

@ -1,473 +0,0 @@
package marathon
import (
"context"
"errors"
"fmt"
"math"
"net"
"strconv"
"strings"
"github.com/gambol99/go-marathon"
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/config/label"
"github.com/traefik/traefik/v2/pkg/provider"
"github.com/traefik/traefik/v2/pkg/provider/constraints"
)
func (p *Provider) buildConfiguration(ctx context.Context, applications *marathon.Applications) *dynamic.Configuration {
configurations := make(map[string]*dynamic.Configuration)
for _, app := range applications.Apps {
logger := log.Ctx(ctx).With().Str("applicationID", app.ID).Logger()
ctxApp := logger.WithContext(ctx)
extraConf, err := p.getConfiguration(app)
if err != nil {
logger.Error().Err(err).Msg("Skip application")
continue
}
labels := stringValueMap(app.Labels)
if app.Constraints != nil {
for i, constraintParts := range *app.Constraints {
key := constraints.MarathonConstraintPrefix + "-" + strconv.Itoa(i)
labels[key] = strings.Join(constraintParts, ":")
}
}
if !p.keepApplication(ctxApp, extraConf, labels) {
continue
}
confFromLabel, err := label.DecodeConfiguration(labels)
if err != nil {
logger.Error().Err(err).Send()
continue
}
var tcpOrUDP bool
if len(confFromLabel.TCP.Routers) > 0 || len(confFromLabel.TCP.Services) > 0 {
tcpOrUDP = true
err := p.buildTCPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.TCP)
if err != nil {
logger.Error().Err(err).Send()
continue
}
provider.BuildTCPRouterConfiguration(ctxApp, confFromLabel.TCP)
}
if len(confFromLabel.UDP.Routers) > 0 || len(confFromLabel.UDP.Services) > 0 {
tcpOrUDP = true
err := p.buildUDPServiceConfiguration(ctxApp, app, extraConf, confFromLabel.UDP)
if err != nil {
logger.Error().Err(err).Send()
} else {
provider.BuildUDPRouterConfiguration(ctxApp, confFromLabel.UDP)
}
}
if tcpOrUDP && len(confFromLabel.HTTP.Routers) == 0 &&
len(confFromLabel.HTTP.Middlewares) == 0 &&
len(confFromLabel.HTTP.Services) == 0 {
configurations[app.ID] = confFromLabel
continue
}
err = p.buildServiceConfiguration(ctxApp, app, extraConf, confFromLabel.HTTP)
if err != nil {
logger.Error().Err(err).Send()
continue
}
model := struct {
Name string
Labels map[string]string
}{
Name: app.ID,
Labels: labels,
}
serviceName := getServiceName(app)
provider.BuildRouterConfiguration(ctxApp, confFromLabel.HTTP, serviceName, p.defaultRuleTpl, model)
configurations[app.ID] = confFromLabel
}
return provider.Merge(ctx, configurations)
}
func getServiceName(app marathon.Application) string {
return strings.ReplaceAll(strings.TrimPrefix(app.ID, "/"), "/", "_")
}
func (p *Provider) buildServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.HTTPConfiguration) error {
appName := getServiceName(app)
logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger()
if len(conf.Services) == 0 {
conf.Services = make(map[string]*dynamic.Service)
lb := &dynamic.ServersLoadBalancer{}
lb.SetDefaults()
conf.Services[appName] = &dynamic.Service{
LoadBalancer: lb,
}
}
for serviceName, service := range conf.Services {
var servers []dynamic.Server
defaultServer := dynamic.Server{}
defaultServer.SetDefaults()
if len(service.LoadBalancer.Servers) > 0 {
defaultServer = service.LoadBalancer.Servers[0]
}
for _, task := range app.Tasks {
if !p.taskFilter(ctx, *task, app) {
continue
}
server, err := p.getServer(app, *task, extraConf, defaultServer)
if err != nil {
logger.Error().Err(err).Msg("Skip task")
continue
}
servers = append(servers, server)
}
if len(servers) == 0 {
return fmt.Errorf("no server for the service %s", serviceName)
}
service.LoadBalancer.Servers = servers
}
return nil
}
func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.TCPConfiguration) error {
appName := getServiceName(app)
logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger()
if len(conf.Services) == 0 {
conf.Services = map[string]*dynamic.TCPService{
appName: {
LoadBalancer: new(dynamic.TCPServersLoadBalancer),
},
}
}
for serviceName, service := range conf.Services {
var servers []dynamic.TCPServer
defaultServer := dynamic.TCPServer{}
if len(service.LoadBalancer.Servers) > 0 {
defaultServer = service.LoadBalancer.Servers[0]
}
for _, task := range app.Tasks {
if p.taskFilter(ctx, *task, app) {
server, err := p.getTCPServer(app, *task, extraConf, defaultServer)
if err != nil {
logger.Error().Err(err).Msg("Skip task")
continue
}
servers = append(servers, server)
}
}
if len(servers) == 0 {
return fmt.Errorf("no server for the service %s", serviceName)
}
service.LoadBalancer.Servers = servers
}
return nil
}
func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, app marathon.Application, extraConf configuration, conf *dynamic.UDPConfiguration) error {
appName := getServiceName(app)
logger := log.Ctx(ctx).With().Str("applicationName", appName).Logger()
if len(conf.Services) == 0 {
conf.Services = make(map[string]*dynamic.UDPService)
lb := &dynamic.UDPServersLoadBalancer{}
conf.Services[appName] = &dynamic.UDPService{
LoadBalancer: lb,
}
}
for serviceName, service := range conf.Services {
var servers []dynamic.UDPServer
defaultServer := dynamic.UDPServer{}
if len(service.LoadBalancer.Servers) > 0 {
defaultServer = service.LoadBalancer.Servers[0]
}
for _, task := range app.Tasks {
if p.taskFilter(ctx, *task, app) {
server, err := p.getUDPServer(app, *task, extraConf, defaultServer)
if err != nil {
logger.Error().Err(err).Msg("Skip task")
continue
}
servers = append(servers, server)
}
}
if len(servers) == 0 {
return fmt.Errorf("no server for the service %s", serviceName)
}
service.LoadBalancer.Servers = servers
}
return nil
}
func (p *Provider) keepApplication(ctx context.Context, extraConf configuration, labels map[string]string) bool {
logger := log.Ctx(ctx)
// Filter disabled application.
if !extraConf.Enable {
logger.Debug().Msg("Filtering disabled Marathon application")
return false
}
// Filter by constraints.
matches, err := constraints.MatchLabels(labels, p.Constraints)
if err != nil {
logger.Error().Err(err).Msg("Error matching constraints expression")
return false
}
if !matches {
logger.Debug().Msgf("Marathon application filtered by constraint expression: %q", p.Constraints)
return false
}
return true
}
func (p *Provider) taskFilter(ctx context.Context, task marathon.Task, application marathon.Application) bool {
if task.State != string(taskStateRunning) {
return false
}
if ready := p.readyChecker.Do(task, application); !ready {
log.Ctx(ctx).Info().Msgf("Filtering unready task %s from application %s", task.ID, application.ID)
return false
}
return true
}
func (p *Provider) getTCPServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.TCPServer) (dynamic.TCPServer, error) {
host, err := p.getServerHost(task, app, extraConf)
if len(host) == 0 {
return dynamic.TCPServer{}, err
}
port, err := getPort(task, app, defaultServer.Port)
if err != nil {
return dynamic.TCPServer{}, err
}
server := dynamic.TCPServer{
Address: net.JoinHostPort(host, port),
}
return server, nil
}
func (p *Provider) getUDPServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.UDPServer) (dynamic.UDPServer, error) {
host, err := p.getServerHost(task, app, extraConf)
if len(host) == 0 {
return dynamic.UDPServer{}, err
}
port, err := getPort(task, app, defaultServer.Port)
if err != nil {
return dynamic.UDPServer{}, err
}
server := dynamic.UDPServer{
Address: net.JoinHostPort(host, port),
}
return server, nil
}
func (p *Provider) getServer(app marathon.Application, task marathon.Task, extraConf configuration, defaultServer dynamic.Server) (dynamic.Server, error) {
host, err := p.getServerHost(task, app, extraConf)
if len(host) == 0 {
return dynamic.Server{}, err
}
port, err := getPort(task, app, defaultServer.Port)
if err != nil {
return dynamic.Server{}, err
}
server := dynamic.Server{
URL: fmt.Sprintf("%s://%s", defaultServer.Scheme, net.JoinHostPort(host, port)),
}
return server, nil
}
func (p *Provider) getServerHost(task marathon.Task, app marathon.Application, extraConf configuration) (string, error) {
networks := app.Networks
var hostFlag bool
if networks == nil {
hostFlag = app.IPAddressPerTask == nil
} else {
hostFlag = (*networks)[0].Mode != marathon.ContainerNetworkMode
}
if hostFlag || p.ForceTaskHostname {
if len(task.Host) == 0 {
return "", fmt.Errorf("host is undefined for task %q app %q", task.ID, app.ID)
}
return task.Host, nil
}
numTaskIPAddresses := len(task.IPAddresses)
switch numTaskIPAddresses {
case 0:
return "", fmt.Errorf("missing IP address for Marathon application %s on task %s", app.ID, task.ID)
case 1:
return task.IPAddresses[0].IPAddress, nil
default:
if extraConf.Marathon.IPAddressIdx == math.MinInt32 {
return "", fmt.Errorf("found %d task IP addresses but missing IP address index for Marathon application %s on task %s",
numTaskIPAddresses, app.ID, task.ID)
}
if extraConf.Marathon.IPAddressIdx < 0 || extraConf.Marathon.IPAddressIdx > numTaskIPAddresses {
return "", fmt.Errorf("cannot use IP address index to select from %d task IP addresses for Marathon application %s on task %s",
numTaskIPAddresses, app.ID, task.ID)
}
return task.IPAddresses[extraConf.Marathon.IPAddressIdx].IPAddress, nil
}
}
func getPort(task marathon.Task, app marathon.Application, serverPort string) (string, error) {
port, err := processPorts(app, task, serverPort)
if err != nil {
return "", fmt.Errorf("unable to process ports for %s %s: %w", app.ID, task.ID, err)
}
return strconv.Itoa(port), nil
}
// processPorts returns the configured port.
// An explicitly specified port is preferred. If none is specified, it selects
// one of the available port. The first such found port is returned unless an
// optional index is provided.
func processPorts(app marathon.Application, task marathon.Task, serverPort string) (int, error) {
if len(serverPort) > 0 && !(strings.HasPrefix(serverPort, "index:") || strings.HasPrefix(serverPort, "name:")) {
port, err := strconv.Atoi(serverPort)
if err != nil {
return 0, err
}
if port <= 0 {
return 0, fmt.Errorf("explicitly specified port %d must be greater than zero", port)
} else if port > 0 {
return port, nil
}
}
if strings.HasPrefix(serverPort, "name:") {
name := strings.TrimPrefix(serverPort, "name:")
port := retrieveNamedPort(app, name)
if port == 0 {
return 0, fmt.Errorf("no port with name %s", name)
}
return port, nil
}
ports := retrieveAvailablePorts(app, task)
if len(ports) == 0 {
return 0, errors.New("no port found")
}
portIndex := 0
if strings.HasPrefix(serverPort, "index:") {
indexString := strings.TrimPrefix(serverPort, "index:")
index, err := strconv.Atoi(indexString)
if err != nil {
return 0, err
}
if index < 0 || index > len(ports)-1 {
return 0, fmt.Errorf("index %d must be within range (0, %d)", index, len(ports)-1)
}
portIndex = index
}
return ports[portIndex], nil
}
func retrieveNamedPort(app marathon.Application, name string) int {
// Using port definition if available
if app.PortDefinitions != nil && len(*app.PortDefinitions) > 0 {
for _, def := range *app.PortDefinitions {
if def.Port != nil && *def.Port > 0 && def.Name == name {
return *def.Port
}
}
}
// If using IP-per-task using this port definition
if app.IPAddressPerTask != nil && app.IPAddressPerTask.Discovery != nil && len(*(app.IPAddressPerTask.Discovery.Ports)) > 0 {
for _, def := range *(app.IPAddressPerTask.Discovery.Ports) {
if def.Number > 0 && def.Name == name {
return def.Number
}
}
}
return 0
}
func retrieveAvailablePorts(app marathon.Application, task marathon.Task) []int {
// Using default port configuration
if len(task.Ports) > 0 {
return task.Ports
}
// Using port definition if available
if app.PortDefinitions != nil && len(*app.PortDefinitions) > 0 {
var ports []int
for _, def := range *app.PortDefinitions {
if def.Port != nil {
ports = append(ports, *def.Port)
}
}
return ports
}
// If using IP-per-task using this port definition
if app.IPAddressPerTask != nil && app.IPAddressPerTask.Discovery != nil && len(*(app.IPAddressPerTask.Discovery.Ports)) > 0 {
var ports []int
for _, def := range *(app.IPAddressPerTask.Discovery.Ports) {
ports = append(ports, def.Number)
}
return ports
}
return []int{}
}

File diff suppressed because it is too large Load diff

View file

@ -1,24 +0,0 @@
package marathon
import (
"errors"
"github.com/gambol99/go-marathon"
"github.com/stretchr/testify/mock"
"github.com/traefik/traefik/v2/pkg/provider/marathon/mocks"
)
type fakeClient struct {
mocks.Marathon
}
func newFakeClient(applicationsError bool, applications marathon.Applications) *fakeClient {
// create an instance of our test object
fakeClient := new(fakeClient)
if applicationsError {
fakeClient.On("Applications", mock.Anything).Return(nil, errors.New("fake Marathon server error"))
} else {
fakeClient.On("Applications", mock.Anything).Return(&applications, nil)
}
return fakeClient
}

View file

@ -1,42 +0,0 @@
package marathon
import (
"math"
"github.com/gambol99/go-marathon"
"github.com/traefik/traefik/v2/pkg/config/label"
)
type configuration struct {
Enable bool
Marathon specificConfiguration
}
type specificConfiguration struct {
IPAddressIdx int
}
func (p *Provider) getConfiguration(app marathon.Application) (configuration, error) {
labels := stringValueMap(app.Labels)
conf := configuration{
Enable: p.ExposedByDefault,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
}
err := label.Decode(labels, &conf, "traefik.marathon.", "traefik.enable")
if err != nil {
return configuration{}, err
}
return conf, nil
}
func stringValueMap(mp *map[string]string) map[string]string {
if mp != nil {
return *mp
}
return make(map[string]string)
}

View file

@ -1,136 +0,0 @@
package marathon
import (
"math"
"testing"
"github.com/gambol99/go-marathon"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetConfiguration(t *testing.T) {
testCases := []struct {
desc string
app marathon.Application
p Provider
expected configuration
}{
{
desc: "Empty labels",
app: marathon.Application{
Constraints: &[][]string{},
Labels: &map[string]string{},
},
p: Provider{
ExposedByDefault: false,
},
expected: configuration{
Enable: false,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
},
},
{
desc: "label enable",
app: marathon.Application{
Constraints: &[][]string{},
Labels: &map[string]string{
"traefik.enable": "true",
},
},
p: Provider{
ExposedByDefault: false,
},
expected: configuration{
Enable: true,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
},
},
{
desc: "Use ip address index",
app: marathon.Application{
Constraints: &[][]string{},
Labels: &map[string]string{
"traefik.marathon.IPAddressIdx": "4",
},
},
p: Provider{
ExposedByDefault: false,
},
expected: configuration{
Enable: false,
Marathon: specificConfiguration{
IPAddressIdx: 4,
},
},
},
{
desc: "Use marathon constraints",
app: marathon.Application{
Constraints: &[][]string{
{"key", "value"},
},
Labels: &map[string]string{},
},
p: Provider{
ExposedByDefault: false,
},
expected: configuration{
Enable: false,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
},
},
{
desc: "ExposedByDefault and no enable label",
app: marathon.Application{
Constraints: &[][]string{},
Labels: &map[string]string{},
},
p: Provider{
ExposedByDefault: true,
},
expected: configuration{
Enable: true,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
},
},
{
desc: "ExposedByDefault and enable label false",
app: marathon.Application{
Constraints: &[][]string{},
Labels: &map[string]string{
"traefik.enable": "false",
},
},
p: Provider{
ExposedByDefault: true,
},
expected: configuration{
Enable: false,
Marathon: specificConfiguration{
IPAddressIdx: math.MinInt32,
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
extraConf, err := test.p.getConfiguration(test.app)
require.NoError(t, err)
assert.Equal(t, test.expected, extraConf)
})
}
}

View file

@ -1,221 +0,0 @@
package marathon
import (
"context"
"fmt"
"net"
"net/http"
"net/url"
"text/template"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/gambol99/go-marathon"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/job"
"github.com/traefik/traefik/v2/pkg/logs"
"github.com/traefik/traefik/v2/pkg/provider"
"github.com/traefik/traefik/v2/pkg/safe"
"github.com/traefik/traefik/v2/pkg/types"
)
const (
// DefaultTemplateRule The default template for the default rule.
DefaultTemplateRule = "Host(`{{ normalize .Name }}`)"
marathonEventIDs = marathon.EventIDApplications |
marathon.EventIDAddHealthCheck |
marathon.EventIDDeploymentSuccess |
marathon.EventIDDeploymentFailed |
marathon.EventIDDeploymentInfo |
marathon.EventIDDeploymentStepSuccess |
marathon.EventIDDeploymentStepFailed
)
// TaskState denotes the Mesos state a task can have.
type TaskState string
const (
taskStateRunning TaskState = "TASK_RUNNING"
taskStateStaging TaskState = "TASK_STAGING"
)
var _ provider.Provider = (*Provider)(nil)
// Provider holds configuration of the provider.
type Provider struct {
Constraints string `description:"Constraints is an expression that Traefik matches against the application's labels to determine whether to create any route for that application." json:"constraints,omitempty" toml:"constraints,omitempty" yaml:"constraints,omitempty" export:"true"`
Trace bool `description:"Display additional provider logs." json:"trace,omitempty" toml:"trace,omitempty" yaml:"trace,omitempty" export:"true"`
Watch bool `description:"Watch provider." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"`
Endpoint string `description:"Marathon server endpoint. You can also specify multiple endpoint for Marathon." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"`
DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"`
ExposedByDefault bool `description:"Expose Marathon apps by default." json:"exposedByDefault,omitempty" toml:"exposedByDefault,omitempty" yaml:"exposedByDefault,omitempty" export:"true"`
DCOSToken string `description:"DCOSToken for DCOS environment, This will override the Authorization header." json:"dcosToken,omitempty" toml:"dcosToken,omitempty" yaml:"dcosToken,omitempty" loggable:"false"`
TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
DialerTimeout ptypes.Duration `description:"Set a dialer timeout for Marathon." json:"dialerTimeout,omitempty" toml:"dialerTimeout,omitempty" yaml:"dialerTimeout,omitempty" export:"true"`
ResponseHeaderTimeout ptypes.Duration `description:"Set a response header timeout for Marathon." json:"responseHeaderTimeout,omitempty" toml:"responseHeaderTimeout,omitempty" yaml:"responseHeaderTimeout,omitempty" export:"true"`
TLSHandshakeTimeout ptypes.Duration `description:"Set a TLS handshake timeout for Marathon." json:"tlsHandshakeTimeout,omitempty" toml:"tlsHandshakeTimeout,omitempty" yaml:"tlsHandshakeTimeout,omitempty" export:"true"`
KeepAlive ptypes.Duration `description:"Set a TCP Keep Alive time." json:"keepAlive,omitempty" toml:"keepAlive,omitempty" yaml:"keepAlive,omitempty" export:"true"`
ForceTaskHostname bool `description:"Force to use the task's hostname." json:"forceTaskHostname,omitempty" toml:"forceTaskHostname,omitempty" yaml:"forceTaskHostname,omitempty" export:"true"`
Basic *Basic `description:"Enable basic authentication." json:"basic,omitempty" toml:"basic,omitempty" yaml:"basic,omitempty" export:"true"`
RespectReadinessChecks bool `description:"Filter out tasks with non-successful readiness checks during deployments." json:"respectReadinessChecks,omitempty" toml:"respectReadinessChecks,omitempty" yaml:"respectReadinessChecks,omitempty" export:"true"`
readyChecker *readinessChecker
marathonClient marathon.Marathon
defaultRuleTpl *template.Template
}
// SetDefaults sets the default values.
func (p *Provider) SetDefaults() {
p.Watch = true
p.Endpoint = "http://127.0.0.1:8080"
p.ExposedByDefault = true
p.DialerTimeout = ptypes.Duration(5 * time.Second)
p.ResponseHeaderTimeout = ptypes.Duration(60 * time.Second)
p.TLSHandshakeTimeout = ptypes.Duration(5 * time.Second)
p.KeepAlive = ptypes.Duration(10 * time.Second)
p.DefaultRule = DefaultTemplateRule
}
// Basic holds basic authentication specific configurations.
type Basic struct {
HTTPBasicAuthUser string `description:"Basic authentication User." json:"httpBasicAuthUser,omitempty" toml:"httpBasicAuthUser,omitempty" yaml:"httpBasicAuthUser,omitempty" loggable:"false"`
HTTPBasicPassword string `description:"Basic authentication Password." json:"httpBasicPassword,omitempty" toml:"httpBasicPassword,omitempty" yaml:"httpBasicPassword,omitempty" loggable:"false"`
}
// Init the provider.
func (p *Provider) Init() error {
fm := template.FuncMap{
"strsToItfs": func(values []string) []interface{} {
var r []interface{}
for _, v := range values {
r = append(r, v)
}
return r
},
}
defaultRuleTpl, err := provider.MakeDefaultRuleTemplate(p.DefaultRule, fm)
if err != nil {
return fmt.Errorf("error while parsing default rule: %w", err)
}
p.defaultRuleTpl = defaultRuleTpl
return nil
}
// Provide allows the marathon provider to provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {
logger := log.With().Str(logs.ProviderName, "marathon").Logger()
ctx := logger.WithContext(context.Background())
operation := func() error {
confg := marathon.NewDefaultConfig()
confg.URL = p.Endpoint
confg.EventsTransport = marathon.EventsTransportSSE
if p.Trace {
confg.LogOutput = logs.NoLevel(logger, zerolog.DebugLevel)
}
if p.Basic != nil {
confg.HTTPBasicAuthUser = p.Basic.HTTPBasicAuthUser
confg.HTTPBasicPassword = p.Basic.HTTPBasicPassword
}
var rc *readinessChecker
if p.RespectReadinessChecks {
logger.Debug().Msg("Enabling Marathon readiness checker")
rc = defaultReadinessChecker(p.Trace)
}
p.readyChecker = rc
if len(p.DCOSToken) > 0 {
confg.DCOSToken = p.DCOSToken
}
TLSConfig, err := p.TLS.CreateTLSConfig(ctx)
if err != nil {
return fmt.Errorf("unable to create client TLS configuration: %w", err)
}
confg.HTTPClient = &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
KeepAlive: time.Duration(p.KeepAlive),
Timeout: time.Duration(p.DialerTimeout),
}).DialContext,
ResponseHeaderTimeout: time.Duration(p.ResponseHeaderTimeout),
TLSHandshakeTimeout: time.Duration(p.TLSHandshakeTimeout),
TLSClientConfig: TLSConfig,
},
}
client, err := marathon.NewClient(confg)
if err != nil {
logger.Error().Err(err).Msg("Failed to create a client for marathon")
return err
}
p.marathonClient = client
if p.Watch {
update, err := client.AddEventsListener(marathonEventIDs)
if err != nil {
logger.Error().Err(err).Msg("Failed to register for events")
return err
}
pool.GoCtx(func(ctxPool context.Context) {
defer close(update)
for {
select {
case <-ctxPool.Done():
return
case event := <-update:
logger.Debug().Msgf("Received provider event %s", event)
conf := p.getConfigurations(ctx)
if conf != nil {
configurationChan <- dynamic.Message{
ProviderName: "marathon",
Configuration: conf,
}
}
}
}
})
}
configuration := p.getConfigurations(ctx)
configurationChan <- dynamic.Message{
ProviderName: "marathon",
Configuration: configuration,
}
return nil
}
notify := func(err error, time time.Duration) {
logger.Error().Err(err).Msgf("Provider error, retrying in %s", time)
}
err := backoff.RetryNotify(safe.OperationWithRecover(operation), backoff.WithContext(job.NewBackOff(backoff.NewExponentialBackOff()), ctx), notify)
if err != nil {
logger.Error().Err(err).Msg("Cannot retrieve data")
}
return nil
}
func (p *Provider) getConfigurations(ctx context.Context) *dynamic.Configuration {
applications, err := p.getApplications()
if err != nil {
log.Ctx(ctx).Error().Err(err).Msg("Failed to retrieve Marathon applications")
return nil
}
return p.buildConfiguration(ctx, applications)
}
func (p *Provider) getApplications() (*marathon.Applications, error) {
v := url.Values{}
v.Add("embed", "apps.tasks")
v.Add("embed", "apps.deployments")
v.Add("embed", "apps.readiness")
return p.marathonClient.Applications(v)
}

File diff suppressed because it is too large Load diff

View file

@ -1,122 +0,0 @@
package marathon
import (
"time"
"github.com/gambol99/go-marathon"
"github.com/rs/zerolog/log"
)
const (
// readinessCheckDefaultTimeout is the default timeout for a readiness
// check if no check timeout is specified on the application spec. This
// should really never be the case, but better be safe than sorry.
readinessCheckDefaultTimeout = 10 * time.Second
// readinessCheckSafetyMargin is some buffer duration to account for
// small offsets in readiness check execution.
readinessCheckSafetyMargin = 5 * time.Second
readinessLogHeader = "Marathon readiness check: "
)
type readinessChecker struct {
checkDefaultTimeout time.Duration
checkSafetyMargin time.Duration
traceLogging bool
}
func defaultReadinessChecker(isTraceLogging bool) *readinessChecker {
return &readinessChecker{
checkDefaultTimeout: readinessCheckDefaultTimeout,
checkSafetyMargin: readinessCheckSafetyMargin,
traceLogging: isTraceLogging,
}
}
func (rc *readinessChecker) Do(task marathon.Task, app marathon.Application) bool {
if rc == nil {
// Readiness checker disabled.
return true
}
switch {
case len(app.Deployments) == 0:
// We only care about readiness during deployments; post-deployment readiness
// can be covered by a periodic post-deployment probe (i.e., Traefik health checks).
rc.tracef("task %s app %s: ready = true [no deployment ongoing]", task.ID, app.ID)
return true
case app.ReadinessChecks == nil || len(*app.ReadinessChecks) == 0:
// Applications without configured readiness checks are always considered
// ready.
rc.tracef("task %s app %s: ready = true [no readiness checks on app]", task.ID, app.ID)
return true
}
// Loop through all readiness check results and return the results for
// matching task IDs.
if app.ReadinessCheckResults != nil {
for _, readinessCheckResult := range *app.ReadinessCheckResults {
if readinessCheckResult.TaskID == task.ID {
rc.tracef("task %s app %s: ready = %t [evaluating readiness check ready state]", task.ID, app.ID, readinessCheckResult.Ready)
return readinessCheckResult.Ready
}
}
}
// There's a corner case sometimes hit where the first new task of a
// deployment goes from TASK_STAGING to TASK_RUNNING without a corresponding
// readiness check result being included in the API response. This only happens
// in a very short (yet unlucky) time frame and does not repeat for subsequent
// tasks of the same deployment.
// Complicating matters, the situation may occur for both initially deploying
// applications as well as rolling-upgraded ones where one or more tasks from
// a previous deployment exist already and are joined by new tasks from a
// subsequent deployment. We must always make sure that pre-existing tasks
// maintain their ready state while newly launched tasks must be considered
// unready until a check result appears.
// We distinguish the two cases by comparing the current time with the start
// time of the task: It should take Marathon at most one readiness check timeout
// interval (plus some safety margin to account for the delayed nature of
// distributed systems) for readiness check results to be returned along the API
// response. Once the task turns old enough, we assume it to be part of a
// pre-existing deployment and mark it as ready. Note that it is okay to err
// on the side of caution and consider a task unready until the safety time
// window has elapsed because a newly created task should be readiness-checked
// and be given a result fairly shortly after its creation (i.e., on the scale
// of seconds).
readinessCheckTimeoutSecs := (*app.ReadinessChecks)[0].TimeoutSeconds
readinessCheckTimeout := time.Duration(readinessCheckTimeoutSecs) * time.Second
if readinessCheckTimeout == 0 {
rc.tracef("task %s app %s: readiness check timeout not set, using default value %s", task.ID, app.ID, rc.checkDefaultTimeout)
readinessCheckTimeout = rc.checkDefaultTimeout
} else {
readinessCheckTimeout += rc.checkSafetyMargin
}
startTime, err := time.Parse(time.RFC3339, task.StartedAt)
if err != nil {
// An unparseable start time should never occur; if it does, we assume the
// problem should be surfaced as quickly as possible, which is easiest if
// we shun the task from rotation.
log.Warn().Err(err).Msgf("Failed to parse start-time %s of task %s from application %s (assuming unready)", task.StartedAt, task.ID, app.ID)
return false
}
since := time.Since(startTime)
if since < readinessCheckTimeout {
rc.tracef("task %s app %s: ready = false [task with start-time %s not within assumed check timeout window of %s (elapsed time since task start: %s)]", task.ID, app.ID, startTime.Format(time.RFC3339), readinessCheckTimeout, since)
return false
}
// Finally, we can be certain this task is not part of the deployment (i.e.,
// it's an old task that's going to transition into the TASK_KILLING and/or
// TASK_KILLED state as new tasks' readiness checks gradually turn green.)
rc.tracef("task %s app %s: ready = true [task with start-time %s not involved in deployment (elapsed time since task start: %s)]", task.ID, app.ID, startTime.Format(time.RFC3339), since)
return true
}
func (rc *readinessChecker) tracef(format string, args ...interface{}) {
if rc.traceLogging {
log.Debug().Msgf(readinessLogHeader+format, args...)
}
}

View file

@ -1,134 +0,0 @@
package marathon
import (
"testing"
"time"
"github.com/gambol99/go-marathon"
)
func testReadinessChecker() *readinessChecker {
return defaultReadinessChecker(false)
}
func TestDisabledReadinessChecker(t *testing.T) {
var rc *readinessChecker
tsk := task()
app := application(
deployments("deploymentId"),
readinessCheck(0),
readinessCheckResult(testTaskName, false),
)
if ready := rc.Do(tsk, app); !ready {
t.Error("expected ready = true")
}
}
func TestEnabledReadinessChecker(t *testing.T) {
tests := []struct {
desc string
task marathon.Task
app marathon.Application
rc readinessChecker
expectedReady bool
}{
{
desc: "no deployment running",
task: task(),
app: application(),
expectedReady: true,
},
{
desc: "no readiness checks defined",
task: task(),
app: application(deployments("deploymentId")),
expectedReady: true,
},
{
desc: "readiness check result negative",
task: task(),
app: application(
deployments("deploymentId"),
readinessCheck(0),
readinessCheckResult("otherTaskID", true),
readinessCheckResult(testTaskName, false),
),
expectedReady: false,
},
{
desc: "readiness check result positive",
task: task(),
app: application(
deployments("deploymentId"),
readinessCheck(0),
readinessCheckResult("otherTaskID", false),
readinessCheckResult(testTaskName, true),
),
expectedReady: true,
},
{
desc: "no readiness check result with default timeout",
task: task(startedAtFromNow(3 * time.Minute)),
app: application(
deployments("deploymentId"),
readinessCheck(0),
),
rc: readinessChecker{
checkDefaultTimeout: 5 * time.Minute,
},
expectedReady: false,
},
{
desc: "no readiness check result with readiness check timeout",
task: task(startedAtFromNow(4 * time.Minute)),
app: application(
deployments("deploymentId"),
readinessCheck(3*time.Minute),
),
rc: readinessChecker{
checkSafetyMargin: 3 * time.Minute,
},
expectedReady: false,
},
{
desc: "invalid task start time",
task: task(startedAt("invalid")),
app: application(
deployments("deploymentId"),
readinessCheck(0),
),
expectedReady: false,
},
{
desc: "task not involved in deployment",
task: task(startedAtFromNow(1 * time.Hour)),
app: application(
deployments("deploymentId"),
readinessCheck(0),
),
rc: readinessChecker{
checkDefaultTimeout: 10 * time.Second,
},
expectedReady: true,
},
}
for _, test := range tests {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
rc := testReadinessChecker()
if test.rc.checkDefaultTimeout > 0 {
rc.checkDefaultTimeout = test.rc.checkDefaultTimeout
}
if test.rc.checkSafetyMargin > 0 {
rc.checkSafetyMargin = test.rc.checkSafetyMargin
}
actualReady := test.rc.Do(test.task, test.app)
if actualReady != test.expectedReady {
t.Errorf("actual ready = %t, expected ready = %t", actualReady, test.expectedReady)
}
})
}
}

View file

@ -1,299 +0,0 @@
package rancher
import (
"context"
"errors"
"fmt"
"net"
"strings"
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/config/label"
"github.com/traefik/traefik/v2/pkg/provider"
"github.com/traefik/traefik/v2/pkg/provider/constraints"
)
func (p *Provider) buildConfiguration(ctx context.Context, services []rancherData) *dynamic.Configuration {
configurations := make(map[string]*dynamic.Configuration)
for _, service := range services {
logger := log.Ctx(ctx).With().Str("service", service.Name).Logger()
ctxService := logger.WithContext(ctx)
if !p.keepService(ctx, service) {
continue
}
confFromLabel, err := label.DecodeConfiguration(service.Labels)
if err != nil {
logger.Error().Err(err).Send()
continue
}
var tcpOrUDP bool
if len(confFromLabel.TCP.Routers) > 0 || len(confFromLabel.TCP.Services) > 0 {
tcpOrUDP = true
err := p.buildTCPServiceConfiguration(ctxService, service, confFromLabel.TCP)
if err != nil {
logger.Error().Err(err).Send()
continue
}
provider.BuildTCPRouterConfiguration(ctxService, confFromLabel.TCP)
}
if len(confFromLabel.UDP.Routers) > 0 || len(confFromLabel.UDP.Services) > 0 {
tcpOrUDP = true
err := p.buildUDPServiceConfiguration(ctxService, service, confFromLabel.UDP)
if err != nil {
logger.Error().Err(err).Send()
continue
}
provider.BuildUDPRouterConfiguration(ctxService, confFromLabel.UDP)
}
if tcpOrUDP && len(confFromLabel.HTTP.Routers) == 0 &&
len(confFromLabel.HTTP.Middlewares) == 0 &&
len(confFromLabel.HTTP.Services) == 0 {
configurations[service.Name] = confFromLabel
continue
}
err = p.buildServiceConfiguration(ctx, service, confFromLabel.HTTP)
if err != nil {
logger.Error().Err(err).Send()
continue
}
model := struct {
Name string
Labels map[string]string
}{
Name: service.Name,
Labels: service.Labels,
}
provider.BuildRouterConfiguration(ctx, confFromLabel.HTTP, service.Name, p.defaultRuleTpl, model)
configurations[service.Name] = confFromLabel
}
return provider.Merge(ctx, configurations)
}
func (p *Provider) buildTCPServiceConfiguration(ctx context.Context, service rancherData, configuration *dynamic.TCPConfiguration) error {
serviceName := service.Name
if len(configuration.Services) == 0 {
configuration.Services = map[string]*dynamic.TCPService{
serviceName: {
LoadBalancer: new(dynamic.TCPServersLoadBalancer),
},
}
}
for _, confService := range configuration.Services {
err := p.addServerTCP(ctx, service, confService.LoadBalancer)
if err != nil {
return err
}
}
return nil
}
func (p *Provider) buildUDPServiceConfiguration(ctx context.Context, service rancherData, configuration *dynamic.UDPConfiguration) error {
serviceName := service.Name
if len(configuration.Services) == 0 {
configuration.Services = make(map[string]*dynamic.UDPService)
lb := &dynamic.UDPServersLoadBalancer{}
configuration.Services[serviceName] = &dynamic.UDPService{
LoadBalancer: lb,
}
}
for _, confService := range configuration.Services {
err := p.addServerUDP(ctx, service, confService.LoadBalancer)
if err != nil {
return err
}
}
return nil
}
func (p *Provider) buildServiceConfiguration(ctx context.Context, service rancherData, configuration *dynamic.HTTPConfiguration) error {
serviceName := service.Name
if len(configuration.Services) == 0 {
configuration.Services = make(map[string]*dynamic.Service)
lb := &dynamic.ServersLoadBalancer{}
lb.SetDefaults()
configuration.Services[serviceName] = &dynamic.Service{
LoadBalancer: lb,
}
}
for _, confService := range configuration.Services {
err := p.addServers(ctx, service, confService.LoadBalancer)
if err != nil {
return err
}
}
return nil
}
func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
logger := log.Ctx(ctx)
if !service.ExtraConf.Enable {
logger.Debug().Msg("Filtering disabled service")
return false
}
matches, err := constraints.MatchLabels(service.Labels, p.Constraints)
if err != nil {
logger.Error().Err(err).Msg("Error matching constraint expression")
return false
}
if !matches {
logger.Debug().Msgf("Service pruned by constraint expression: %q", p.Constraints)
return false
}
if p.EnableServiceHealthFilter {
if service.Health != "" && service.Health != healthy && service.Health != updatingHealthy {
logger.Debug().Msgf("Filtering service %s with healthState of %s", service.Name, service.Health)
return false
}
if service.State != "" && service.State != active && service.State != updatingActive && service.State != upgraded && service.State != upgrading {
logger.Debug().Msgf("Filtering service %s with state of %s", service.Name, service.State)
return false
}
}
return true
}
func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error {
log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name)
if loadBalancer == nil {
return errors.New("load-balancer is not defined")
}
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.TCPServer{{}}
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
}
if port == "" {
return errors.New("port is missing")
}
var servers []dynamic.TCPServer
for _, containerIP := range service.Containers {
servers = append(servers, dynamic.TCPServer{
Address: net.JoinHostPort(containerIP, port),
})
}
loadBalancer.Servers = servers
return nil
}
func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error {
log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name)
if loadBalancer == nil {
return errors.New("load-balancer is not defined")
}
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.UDPServer{{}}
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
}
if port == "" {
return errors.New("port is missing")
}
var servers []dynamic.UDPServer
for _, containerIP := range service.Containers {
servers = append(servers, dynamic.UDPServer{
Address: net.JoinHostPort(containerIP, port),
})
}
loadBalancer.Servers = servers
return nil
}
func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error {
log.Ctx(ctx).Debug().Msgf("Trying to add servers for service %s", service.Name)
if loadBalancer == nil {
return errors.New("load-balancer is not defined")
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{}
server.SetDefaults()
loadBalancer.Servers = []dynamic.Server{server}
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
}
if port == "" {
return errors.New("port is missing")
}
var servers []dynamic.Server
for _, containerIP := range service.Containers {
servers = append(servers, dynamic.Server{
URL: fmt.Sprintf("%s://%s", loadBalancer.Servers[0].Scheme, net.JoinHostPort(containerIP, port)),
})
}
loadBalancer.Servers = servers
return nil
}
func getServicePort(data rancherData) string {
rawPort := strings.Split(data.Port, "/")[0]
hostPort := strings.Split(rawPort, ":")
if len(hostPort) >= 2 {
return hostPort[1]
}
if len(hostPort) > 0 && hostPort[0] != "" {
return hostPort[0]
}
return rawPort
}

File diff suppressed because it is too large Load diff

View file

@ -1,22 +0,0 @@
package rancher
import (
"github.com/traefik/traefik/v2/pkg/config/label"
)
type configuration struct {
Enable bool
}
func (p *Provider) getConfiguration(service rancherData) (configuration, error) {
conf := configuration{
Enable: p.ExposedByDefault,
}
err := label.Decode(service.Labels, &conf, "traefik.rancher.", "traefik.enable")
if err != nil {
return configuration{}, err
}
return conf, nil
}

Some files were not shown because too many files have changed in this diff Show more