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.
|
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
|
## 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
|
* `/`: 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
|
* `/health`: `GET` json metrics
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ curl -s "http://localhost:8080/health" | jq .
|
$ curl -s "http://localhost:8080/health" | jq .
|
||||||
{
|
{
|
||||||
"average_response_time_sec": 0,
|
// Træfɪk PID
|
||||||
"average_response_time": "0",
|
"pid": 2458,
|
||||||
"total_response_time_sec": 0,
|
// Træfɪk server uptime (formated time)
|
||||||
"total_response_time": "0",
|
"uptime": "39m6.885931127s",
|
||||||
"total_count": 0,
|
// Træfɪk server uptime in seconds
|
||||||
"pid": 12861,
|
"uptime_sec": 2346.885931127,
|
||||||
"uptime": "7m12.80607635s",
|
// current server date
|
||||||
"uptime_sec": 432.80607635,
|
"time": "2015-10-07 18:32:24.362238909 +0200 CEST",
|
||||||
"time": "2015-09-22 10:25:16.448023473 +0200 CEST",
|
// current server date in seconds
|
||||||
"unixtime": 1442910316,
|
"unixtime": 1444235544,
|
||||||
"status_code_count": {},
|
// count HTTP response status code in realtime
|
||||||
"total_status_code_count": {},
|
"status_code_count": {
|
||||||
"count": 0
|
"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`: `GET` providers
|
||||||
* `/api/providers/{provider}`: `GET` or `PUT` provider
|
- `/api/providers/{provider}`: `GET` or `PUT` provider
|
||||||
* `/api/providers/{provider}/backends`: `GET` backends
|
- `/api/providers/{provider}/backends`: `GET` backends
|
||||||
* `/api/providers/{provider}/backends/{backend}`: `GET` a backend
|
- `/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`: `GET` servers in a backend
|
||||||
* `/api/providers/{provider}/backends/{backend}/servers/{server}`: `GET` a server 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`: `GET` frontends
|
||||||
* `/api/providers/{provider}/frontends/{frontend}`: `GET` a frontend
|
- `/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
|
## <a id="docker"></a> Docker backend
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (s *SimpleSuite) TestSimpleDefaultConfig(c *check.C) {
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
// TODO validate : run on 80
|
// TODO validate : run on 80
|
||||||
resp, err := http.Get("http://127.0.0.1/")
|
resp, err := http.Get("http://127.0.0.1/")
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (s *ConsulSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
// TODO validate : run on 80
|
// TODO validate : run on 80
|
||||||
resp, err := http.Get("http://127.0.0.1/")
|
resp, err := http.Get("http://127.0.0.1/")
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ func (s *DockerSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
// TODO validate : run on 80
|
// TODO validate : run on 80
|
||||||
resp, err := http.Get("http://127.0.0.1/")
|
resp, err := http.Get("http://127.0.0.1/")
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (s *FileSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
// TODO validate : run on 80
|
// TODO validate : run on 80
|
||||||
resp, err := http.Get("http://127.0.0.1/")
|
resp, err := http.Get("http://127.0.0.1/")
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ func (s *MarathonSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
// TODO validate : run on 80
|
// TODO validate : run on 80
|
||||||
resp, err := http.Get("http://127.0.0.1/")
|
resp, err := http.Get("http://127.0.0.1/")
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,195 @@
|
||||||
|
|
||||||
var vm = this;
|
var vm = this;
|
||||||
|
|
||||||
vm.health = Health.get();
|
vm.graph = {
|
||||||
|
averageResponseTime: {},
|
||||||
|
totalStatusCodeCount: {}
|
||||||
|
}
|
||||||
|
|
||||||
var intervalId = $interval(function () {
|
vm.graph.totalStatusCodeCount.options = {
|
||||||
Health.get(function (health) {
|
"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;
|
vm.health = health;
|
||||||
}, function (error) {
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action when load datas failed
|
||||||
|
*
|
||||||
|
* @param {Object} error Error state object
|
||||||
|
*/
|
||||||
|
function erroData(error) {
|
||||||
vm.health = {};
|
vm.health = {};
|
||||||
$log.error(error);
|
$log.error(error);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// first load
|
||||||
|
Health.get(loadData, erroData);
|
||||||
|
|
||||||
|
// Auto refresh data
|
||||||
|
var intervalId = $interval(function () {
|
||||||
|
Health.get(loadData, erroData);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
|
// Stop auto refresh when page change
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
$interval.cancel(intervalId);
|
$interval.cancel(intervalId);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,45 +2,42 @@
|
||||||
<h1 class="text-danger">
|
<h1 class="text-danger">
|
||||||
<span class="glyphicon glyphicon-heart" aria-hidden="true"></span> Health
|
<span class="glyphicon glyphicon-heart" aria-hidden="true"></span> Health
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<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">
|
<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">
|
<li class="list-group-item">
|
||||||
<span>Total response time :</span><span class="badge">{{healthCtrl.health.total_response_time}}</span>
|
<span>Total response time :</span><span class="badge">{{healthCtrl.health.total_response_time}}</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item">
|
</ul>
|
||||||
<span>Total count :</span><span class="badge">{{healthCtrl.health.total_count}}</span>
|
<ul class="list-group">
|
||||||
</li>
|
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<span>PID :</span><span class="badge">{{healthCtrl.health.pid}}</span>
|
<span>PID :</span><span class="badge">{{healthCtrl.health.pid}}</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<span>Uptime :</span><span class="badge">{{healthCtrl.health.uptime}}</span>
|
<span>Uptime :</span><span class="badge">{{healthCtrl.health.uptime}}</span>
|
||||||
</li>
|
</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">
|
<li class="list-group-item">
|
||||||
<span>Uptime sec :</span><span class="badge">{{healthCtrl.health.uptime_sec}}</span>
|
<span>Total count :</span><span class="badge">{{healthCtrl.health.total_count}}</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>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<span>Count :</span><span class="badge">{{healthCtrl.health.count}}</span>
|
<span>Count :</span><span class="badge">{{healthCtrl.health.count}}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
.module('traefik.section', [
|
.module('traefik.section', [
|
||||||
'ui.router',
|
'ui.router',
|
||||||
'ui.bootstrap',
|
'ui.bootstrap',
|
||||||
|
'nvd3',
|
||||||
'traefik.section.providers',
|
'traefik.section.providers',
|
||||||
'traefik.section.health'
|
'traefik.section.health'
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "traefik",
|
"name": "traefik",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"homepage": "https://github.com/ldez/traefik",
|
"homepage": "http://traefik.io",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Fernandez Ludovic <ludovic.fernandez@zenika.com>"
|
"Fernandez Ludovic <ludovic.fernandez@zenika.com>"
|
||||||
],
|
],
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
"bootstrap": "~3.3.5",
|
"bootstrap": "~3.3.5",
|
||||||
"angular-resource": "~1.4.7",
|
"angular-resource": "~1.4.7",
|
||||||
"angular-ui-router": "~0.2.15",
|
"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/bootstrap/dist/css/bootstrap-theme.min.css">
|
||||||
<link rel="stylesheet" href="bower_components/angular-bootstrap/ui-bootstrap-csp.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">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -57,6 +60,9 @@
|
||||||
<script src="bower_components/angular-resource/angular-resource.min.js"></script>
|
<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-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/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 -->
|
<!-- end vendors -->
|
||||||
|
|
||||||
<script src="app/traefik.js"></script>
|
<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)
|
- [UI Router - Documentation](https://github.com/angular-ui/ui-router/wiki)
|
||||||
- [Bootstrap](http://getbootstrap.com)
|
- [Bootstrap](http://getbootstrap.com)
|
||||||
- [Angular Bootstrap](https://angular-ui.github.io/bootstrap)
|
- [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}/backends/{backend}/servers/{server}").HandlerFunc(getServerHandler)
|
||||||
systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends").HandlerFunc(getFrontendsHandler)
|
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}").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
|
// Expose dashboard
|
||||||
systemRouter.Methods("GET").Path("/").HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
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)
|
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) {
|
func getServersHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
vars := mux.Vars(request)
|
vars := mux.Vars(request)
|
||||||
providerID := vars["provider"]
|
providerID := vars["provider"]
|
||||||
|
@ -166,3 +145,55 @@ func getServerHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
}
|
}
|
||||||
http.NotFound(response, 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