Merge branch 'master' into emilevauge-add-traefik-domain
This commit is contained in:
commit
13f621a9ed
21 changed files with 358 additions and 204 deletions
|
@ -72,7 +72,8 @@ Refer to the [benchmarks section](docs/index.md#benchmarks) in the documentation
|
|||
|
||||
You can access to a simple HTML frontend of Træfik.
|
||||
|
||||
![HTML frontend](docs/img/web.frontend.png)
|
||||
![Web UI Providers](docs/img/web.frontend.png)
|
||||
![Web UI Health](docs/img/traefik-health.png)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
BIN
docs/img/traefik-health.png
Normal file
BIN
docs/img/traefik-health.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 53 KiB |
|
@ -232,26 +232,46 @@ address = ":8080"
|
|||
|
||||
* `/`: provides a simple HTML frontend of Træfik
|
||||
|
||||
![HTML frontend](img/web.frontend.png)
|
||||
![Web UI Providers](img/web.frontend.png)
|
||||
![Web UI Health](img/traefik-health.png)
|
||||
|
||||
* `/health`: `GET` json metrics
|
||||
|
||||
```sh
|
||||
$ curl -s "http://localhost:8080/health" | jq .
|
||||
{
|
||||
"average_response_time_sec": 0,
|
||||
"average_response_time": "0",
|
||||
"total_response_time_sec": 0,
|
||||
"total_response_time": "0",
|
||||
"total_count": 0,
|
||||
"pid": 12861,
|
||||
"uptime": "7m12.80607635s",
|
||||
"uptime_sec": 432.80607635,
|
||||
"time": "2015-09-22 10:25:16.448023473 +0200 CEST",
|
||||
"unixtime": 1442910316,
|
||||
"status_code_count": {},
|
||||
"total_status_code_count": {},
|
||||
"count": 0
|
||||
// Træfɪk PID
|
||||
"pid": 2458,
|
||||
// Træfɪk server uptime (formated time)
|
||||
"uptime": "39m6.885931127s",
|
||||
// Træfɪk server uptime in seconds
|
||||
"uptime_sec": 2346.885931127,
|
||||
// current server date
|
||||
"time": "2015-10-07 18:32:24.362238909 +0200 CEST",
|
||||
// current server date in seconds
|
||||
"unixtime": 1444235544,
|
||||
// count HTTP response status code in realtime
|
||||
"status_code_count": {
|
||||
"502": 1
|
||||
},
|
||||
// count HTTP response status code since Træfɪk started
|
||||
"total_status_code_count": {
|
||||
"200": 7,
|
||||
"404": 21,
|
||||
"502": 13
|
||||
},
|
||||
// count HTTP response
|
||||
"count": 1,
|
||||
// count HTTP response
|
||||
"total_count": 41,
|
||||
// sum of all response time (formated time)
|
||||
"total_response_time": "35.456865605s",
|
||||
// sum of all response time in seconds
|
||||
"total_response_time_sec": 35.456865605,
|
||||
// average response time (formated time)
|
||||
"average_response_time": "864.8016ms",
|
||||
// average response time in seconds
|
||||
"average_response_time_sec": 0.8648016000000001
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -321,14 +341,16 @@ $ curl -s "http://localhost:8080/api" | jq .
|
|||
}
|
||||
```
|
||||
|
||||
* `/api/providers`: `GET` providers
|
||||
* `/api/providers/{provider}`: `GET` or `PUT` provider
|
||||
* `/api/providers/{provider}/backends`: `GET` backends
|
||||
* `/api/providers/{provider}/backends/{backend}`: `GET` a backend
|
||||
* `/api/providers/{provider}/backends/{backend}/servers`: `GET` servers in a backend
|
||||
* `/api/providers/{provider}/backends/{backend}/servers/{server}`: `GET` a server in a backend
|
||||
* `/api/providers/{provider}/frontends`: `GET` frontends
|
||||
* `/api/providers/{provider}/frontends/{frontend}`: `GET` a frontend
|
||||
- `/api/providers`: `GET` providers
|
||||
- `/api/providers/{provider}`: `GET` or `PUT` provider
|
||||
- `/api/providers/{provider}/backends`: `GET` backends
|
||||
- `/api/providers/{provider}/backends/{backend}`: `GET` a backend
|
||||
- `/api/providers/{provider}/backends/{backend}/servers`: `GET` servers in a backend
|
||||
- `/api/providers/{provider}/backends/{backend}/servers/{server}`: `GET` a server in a backend
|
||||
- `/api/providers/{provider}/frontends`: `GET` frontends
|
||||
- `/api/providers/{provider}/frontends/{frontend}`: `GET` a frontend
|
||||
- `/api/providers/{provider}/frontends/{frontend}/routes`: `GET` routes in a frontend
|
||||
- `/api/providers/{provider}/frontends/{frontend}/routes/{route}`: `GET` a route in a frontend
|
||||
|
||||
|
||||
## <a id="docker"></a> Docker backend
|
||||
|
|
|
@ -38,7 +38,7 @@ func (s *SimpleSuite) TestSimpleDefaultConfig(c *check.C) {
|
|||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1/")
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
|||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1/")
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
|||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1/")
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
|
|||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1/")
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) {
|
|||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
// TODO validate : run on 80
|
||||
resp, err := http.Get("http://127.0.0.1/")
|
||||
|
||||
|
|
|
@ -6,21 +6,199 @@
|
|||
|
||||
var vm = this;
|
||||
|
||||
vm.health = Health.get();
|
||||
vm.graph = {
|
||||
averageResponseTime: {},
|
||||
totalStatusCodeCount: {}
|
||||
}
|
||||
|
||||
vm.graph.totalStatusCodeCount.options = {
|
||||
"chart": {
|
||||
type: 'discreteBarChart',
|
||||
height: 200,
|
||||
margin: {
|
||||
top: 20,
|
||||
right: 20,
|
||||
bottom: 40,
|
||||
left: 55
|
||||
},
|
||||
x: function (d) {
|
||||
return d.label;
|
||||
},
|
||||
y: function (d) {
|
||||
return d.value;
|
||||
},
|
||||
showValues: true,
|
||||
valueFormat: function (d) {
|
||||
return d3.format('d')(d);
|
||||
},
|
||||
transitionDuration: 50,
|
||||
yAxis: {
|
||||
axisLabelDistance: 30
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"enable": true,
|
||||
"text": "Total Status Code Count",
|
||||
"css": {
|
||||
"textAlign": "center"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
vm.graph.totalStatusCodeCount.data = [
|
||||
{
|
||||
key: "Total Status Code Count",
|
||||
values: [
|
||||
{
|
||||
"label": "200",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Update Total Status Code Count graph
|
||||
*
|
||||
* @param {Object} totalStatusCodeCount Object from API
|
||||
*/
|
||||
function updateTotalStatusCodeCount(totalStatusCodeCount) {
|
||||
|
||||
// extract values
|
||||
vm.graph.totalStatusCodeCount.data[0].values = [];
|
||||
for (var code in totalStatusCodeCount) {
|
||||
if (totalStatusCodeCount.hasOwnProperty(code)) {
|
||||
vm.graph.totalStatusCodeCount.data[0].values.push({
|
||||
label: code,
|
||||
value: totalStatusCodeCount[code]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Update Total Status Code Count graph render
|
||||
if (vm.graph.totalStatusCodeCount.api) {
|
||||
vm.graph.totalStatusCodeCount.api.update();
|
||||
} else {
|
||||
console.error('fail');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vm.graph.averageResponseTime.options = {
|
||||
chart: {
|
||||
type: 'lineChart',
|
||||
height: 200,
|
||||
margin: {
|
||||
top: 20,
|
||||
right: 40,
|
||||
bottom: 40,
|
||||
left: 55
|
||||
},
|
||||
transitionDuration: 50,
|
||||
x: function (d) {
|
||||
return d.x;
|
||||
},
|
||||
y: function (d) {
|
||||
return d.y;
|
||||
},
|
||||
useInteractiveGuideline: true,
|
||||
xAxis: {
|
||||
tickFormat: function (d) {
|
||||
return d3.time.format('%X')(new Date(d));
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
tickFormat: function (d) {
|
||||
return d3.format(',.1f')(d);
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"enable": true,
|
||||
"text": "Average response time",
|
||||
"css": {
|
||||
"textAlign": "center"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var initialPoint = {
|
||||
x: Date.now() - 3000,
|
||||
y: 0
|
||||
};
|
||||
vm.graph.averageResponseTime.data = [
|
||||
{
|
||||
values: [initialPoint],
|
||||
key: 'Average response time (ms)',
|
||||
type: 'line',
|
||||
color: '#2ca02c'
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Update average response time graph
|
||||
*
|
||||
* @param {Number} x Coordinate X
|
||||
* @param {Number} y Coordinate Y
|
||||
*/
|
||||
function updateAverageResponseTimeGraph(x, y) {
|
||||
|
||||
// x multiply 1000 by because unix time is in seconds and JS Date are in milliseconds
|
||||
var data = {
|
||||
x: x * 1000,
|
||||
y: y * 1000
|
||||
};
|
||||
vm.graph.averageResponseTime.data[0].values.push(data);
|
||||
// limit graph entries
|
||||
if (vm.graph.averageResponseTime.data[0].values.length > 100) {
|
||||
vm.graph.averageResponseTime.data[0].values.shift();
|
||||
}
|
||||
|
||||
// Update Average Response Time graph render
|
||||
if (vm.graph.averageResponseTime.api) {
|
||||
vm.graph.averageResponseTime.api.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all graph's datas
|
||||
*
|
||||
* @param {Object} health Health data from server
|
||||
*/
|
||||
function loadData(health) {
|
||||
// Load datas and update Average Response Time graph render
|
||||
updateAverageResponseTimeGraph(health.unixtime, health.average_response_time_sec);
|
||||
|
||||
// Load datas and update Total Status Code Count graph render
|
||||
updateTotalStatusCodeCount(health.total_status_code_count);
|
||||
|
||||
// set data's view
|
||||
vm.health = health;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action when load datas failed
|
||||
*
|
||||
* @param {Object} error Error state object
|
||||
*/
|
||||
function erroData(error) {
|
||||
vm.health = {};
|
||||
$log.error(error);
|
||||
}
|
||||
|
||||
// first load
|
||||
Health.get(loadData, erroData);
|
||||
|
||||
// Auto refresh data
|
||||
var intervalId = $interval(function () {
|
||||
Health.get(function (health) {
|
||||
vm.health = health;
|
||||
}, function (error) {
|
||||
vm.health = {};
|
||||
$log.error(error);
|
||||
});
|
||||
Health.get(loadData, erroData);
|
||||
}, 3000);
|
||||
|
||||
// Stop auto refresh when page change
|
||||
$scope.$on('$destroy', function () {
|
||||
$interval.cancel(intervalId);
|
||||
});
|
||||
|
||||
}]);
|
||||
}]);
|
||||
|
||||
})();
|
||||
|
|
|
@ -2,45 +2,42 @@
|
|||
<h1 class="text-danger">
|
||||
<span class="glyphicon glyphicon-heart" aria-hidden="true"></span> Health
|
||||
</h1>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<span>Average response time sec :</span><span class="badge">{{healthCtrl.health.average_response_time_sec}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Average response time :</span><span class="badge">{{healthCtrl.health.average_response_time}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Total response time sec :</span><span class="badge">{{healthCtrl.health.total_response_time_sec}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Total response time :</span><span class="badge">{{healthCtrl.health.total_response_time}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Total count :</span><span class="badge">{{healthCtrl.health.total_count}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>PID :</span><span class="badge">{{healthCtrl.health.pid}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Uptime :</span><span class="badge">{{healthCtrl.health.uptime}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Uptime sec :</span><span class="badge">{{healthCtrl.health.uptime_sec}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Time :</span><span class="badge">{{healthCtrl.health.time}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Unixtime :</span><span class="badge">{{healthCtrl.health.unixtime}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Status code count :</span><span class="badge">{{healthCtrl.health.status_code_count}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Total status code count :</span><span class="badge">{{healthCtrl.health.total_status_code_count}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Count :</span><span class="badge">{{healthCtrl.health.count}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<nvd3 options="healthCtrl.graph.averageResponseTime.options" data="healthCtrl.graph.averageResponseTime.data" api="healthCtrl.graph.averageResponseTime.api"></nvd3>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<span>Total response time :</span><span class="badge">{{healthCtrl.health.total_response_time}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<span>PID :</span><span class="badge">{{healthCtrl.health.pid}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Uptime :</span><span class="badge">{{healthCtrl.health.uptime}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<nvd3 options="healthCtrl.graph.totalStatusCodeCount.options" data="healthCtrl.graph.totalStatusCodeCount.data" api="healthCtrl.graph.totalStatusCodeCount.api"></nvd3>
|
||||
</div>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<span>Total count :</span><span class="badge">{{healthCtrl.health.total_count}}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<span>Count :</span><span class="badge">{{healthCtrl.health.count}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
.module('traefik.section', [
|
||||
'ui.router',
|
||||
'ui.bootstrap',
|
||||
'nvd3',
|
||||
'traefik.section.providers',
|
||||
'traefik.section.health'
|
||||
]);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "traefik",
|
||||
"version": "1.0.0",
|
||||
"homepage": "https://github.com/ldez/traefik",
|
||||
"homepage": "http://traefik.io",
|
||||
"authors": [
|
||||
"Fernandez Ludovic <ludovic.fernandez@zenika.com>"
|
||||
],
|
||||
|
@ -20,6 +20,7 @@
|
|||
"bootstrap": "~3.3.5",
|
||||
"angular-resource": "~1.4.7",
|
||||
"angular-ui-router": "~0.2.15",
|
||||
"angular-bootstrap": "~0.13.4"
|
||||
"angular-bootstrap": "~0.13.4",
|
||||
"angular-nvd3": "~1.0.2"
|
||||
}
|
||||
}
|
||||
|
|
1
static/bower_components/angular-nvd3/dist/angular-nvd3.min.js
vendored
Normal file
1
static/bower_components/angular-nvd3/dist/angular-nvd3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5
static/bower_components/d3/d3.min.js
vendored
Normal file
5
static/bower_components/d3/d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/bower_components/nvd3/build/nv.d3.min.css
vendored
Normal file
1
static/bower_components/nvd3/build/nv.d3.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
8
static/bower_components/nvd3/build/nv.d3.min.js
vendored
Normal file
8
static/bower_components/nvd3/build/nv.d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -13,6 +13,9 @@
|
|||
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.min.css">
|
||||
<link rel="stylesheet" href="bower_components/angular-bootstrap/ui-bootstrap-csp.css">
|
||||
|
||||
<!-- NVD3 -->
|
||||
<link rel="stylesheet" href="bower_components/nvd3/build/nv.d3.min.css">
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
|
||||
|
@ -57,6 +60,9 @@
|
|||
<script src="bower_components/angular-resource/angular-resource.min.js"></script>
|
||||
<script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script>
|
||||
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
|
||||
<script src="bower_components/d3/d3.min.js"></script>
|
||||
<script src="bower_components/nvd3/build/nv.d3.min.js"></script>
|
||||
<script src="bower_components/angular-nvd3/dist/angular-nvd3.min.js"></script>
|
||||
<!-- end vendors -->
|
||||
|
||||
<script src="app/traefik.js"></script>
|
||||
|
|
|
@ -26,4 +26,7 @@ Do `npm install` and `bower install`
|
|||
- [UI Router - Documentation](https://github.com/angular-ui/ui-router/wiki)
|
||||
- [Bootstrap](http://getbootstrap.com)
|
||||
- [Angular Bootstrap](https://angular-ui.github.io/bootstrap)
|
||||
|
||||
- [D3](http://d3js.org)
|
||||
- [D3 - Documentation](https://github.com/mbostock/d3/wiki)
|
||||
- [NVD3](http://nvd3.org)
|
||||
- [Angular nvD3](http://krispo.github.io/angular-nvd3)
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>/ˈTræfɪk/</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap-theme.min.css">
|
||||
<script src="/static/jquery-2.1.4.min.js"></script>
|
||||
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {padding-bottom: 70px;}
|
||||
.content {margin:10px;}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<div class="jumbotron">
|
||||
<h1>/ˈTræfɪk/</h1>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
<!-- <div class="panel-heading">Frontends</div>
|
||||
<div class="panel-body"> -->
|
||||
{{range $keyProviders, $valueProviders := .Configurations}}
|
||||
{{range $keyFrontends, $valueFrontends := $valueProviders.Frontends}}
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">{{$keyFrontends}} - ({{$keyProviders}})</div>
|
||||
<div class="panel-body">
|
||||
<a class="btn btn-info" role="button" data-toggle="collapse" href="#{{$valueFrontends.Backend}}" aria-expanded="false">
|
||||
{{$valueFrontends.Backend}}
|
||||
</a>
|
||||
</div>
|
||||
<table class="table table-striped table-hover">
|
||||
<tr>
|
||||
<td><em>Route</em></td>
|
||||
<td><em>Rule</em></td>
|
||||
<td><em>Value</em></td>
|
||||
</tr>
|
||||
{{range $keyRoutes, $valueRoutes := $valueFrontends.Routes}}
|
||||
<tr>
|
||||
<td>{{$keyRoutes}}</td>
|
||||
<td>{{$valueRoutes.Rule}}</td>
|
||||
<td>{{$valueRoutes.Value}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<!-- <div class="panel-heading">Backends</div>
|
||||
<div class="panel-body"> -->
|
||||
{{range $keyProviders, $valueProviders := .Configurations}}
|
||||
{{range $keyBackends, $valueBackends := $valueProviders.Backends}}
|
||||
<div class="panel panel-primary" id="{{$keyBackends}}">
|
||||
<div class="panel-heading">{{$keyBackends}} - ({{$keyProviders}})</div>
|
||||
<div class="panel-body">
|
||||
{{with $valueBackends.LoadBalancer}}
|
||||
<a class="btn btn-info" role="button">
|
||||
Load Balancer: {{.Method}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{with $valueBackends.CircuitBreaker}}
|
||||
<a class="btn btn-info" role="button">
|
||||
Circuit Breaker: {{.Expression}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<table class="table table-striped table-hover">
|
||||
<tr>
|
||||
<td><em>Server</em></td>
|
||||
<td><em>URL</em></td>
|
||||
<td><em>Weight</em></td>
|
||||
</tr>
|
||||
{{range $keyServers, $valueServers := $valueBackends.Servers}}
|
||||
<tr>
|
||||
<td>{{$keyServers}}</td>
|
||||
<td><code><A href="{{$valueServers.URL}}">{{$valueServers.URL}}</A></code></td>
|
||||
<td>{{$valueServers.Weight}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
77
web.go
77
web.go
|
@ -51,6 +51,8 @@ func (provider *WebProvider) Provide(configurationChan chan<- configMessage) err
|
|||
systemRouter.Methods("GET").Path("/api/providers/{provider}/backends/{backend}/servers/{server}").HandlerFunc(getServerHandler)
|
||||
systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends").HandlerFunc(getFrontendsHandler)
|
||||
systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends/{frontend}").HandlerFunc(getFrontendHandler)
|
||||
systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends/{frontend}/routes").HandlerFunc(getRoutesHandler)
|
||||
systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends/{frontend}/routes/{route}").HandlerFunc(getRouteHandler)
|
||||
|
||||
// Expose dashboard
|
||||
systemRouter.Methods("GET").Path("/").HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
||||
|
@ -115,29 +117,6 @@ func getBackendHandler(response http.ResponseWriter, request *http.Request) {
|
|||
http.NotFound(response, request)
|
||||
}
|
||||
|
||||
func getFrontendsHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
if provider, ok := currentConfigurations[providerID]; ok {
|
||||
templatesRenderer.JSON(response, http.StatusOK, provider.Frontends)
|
||||
} else {
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
}
|
||||
|
||||
func getFrontendHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
frontendID := vars["frontend"]
|
||||
if provider, ok := currentConfigurations[providerID]; ok {
|
||||
if frontend, ok := provider.Frontends[frontendID]; ok {
|
||||
templatesRenderer.JSON(response, http.StatusOK, frontend)
|
||||
return
|
||||
}
|
||||
}
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
|
||||
func getServersHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
|
@ -166,3 +145,55 @@ func getServerHandler(response http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
|
||||
func getFrontendsHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
if provider, ok := currentConfigurations[providerID]; ok {
|
||||
templatesRenderer.JSON(response, http.StatusOK, provider.Frontends)
|
||||
} else {
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
}
|
||||
|
||||
func getFrontendHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
frontendID := vars["frontend"]
|
||||
if provider, ok := currentConfigurations[providerID]; ok {
|
||||
if frontend, ok := provider.Frontends[frontendID]; ok {
|
||||
templatesRenderer.JSON(response, http.StatusOK, frontend)
|
||||
return
|
||||
}
|
||||
}
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
|
||||
func getRoutesHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
frontendID := vars["frontend"]
|
||||
if provider, ok := currentConfigurations[providerID]; ok {
|
||||
if frontend, ok := provider.Frontends[frontendID]; ok {
|
||||
templatesRenderer.JSON(response, http.StatusOK, frontend.Routes)
|
||||
return
|
||||
}
|
||||
}
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
|
||||
func getRouteHandler(response http.ResponseWriter, request *http.Request) {
|
||||
vars := mux.Vars(request)
|
||||
providerID := vars["provider"]
|
||||
frontendID := vars["frontend"]
|
||||
routeID := vars["route"]
|
||||
if provider, ok := currentConfigurations[providerID]; ok {
|
||||
if frontend, ok := provider.Frontends[frontendID]; ok {
|
||||
if route, ok := frontend.Routes[routeID]; ok {
|
||||
templatesRenderer.JSON(response, http.StatusOK, route)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
http.NotFound(response, request)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue