style(dashboard): update dashboard information (#2079)

* style(dashboard): update dashboard information

* docs(swagger): update swagger.yml
pull/2080/head
Anthony Lapenna 2018-07-25 20:47:33 +02:00 committed by GitHub
parent 3306cbaa27
commit 134a38a566
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 113 deletions

View File

@ -23,5 +23,12 @@ func (handler *Handler) endpointInspect(w http.ResponseWriter, r *http.Request)
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an endpoint with the specified identifier inside the database", err}
}
err = handler.requestBouncer.EndpointAccess(r, endpoint)
if err != nil {
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access endpoint", portainer.ErrEndpointAccessDenied}
}
hideFields(endpoint)
return response.JSON(w, endpoint)
}

View File

@ -25,6 +25,7 @@ func hideFields(endpoint *portainer.Endpoint) {
type Handler struct {
*mux.Router
authorizeEndpointManagement bool
requestBouncer *security.RequestBouncer
EndpointService portainer.EndpointService
EndpointGroupService portainer.EndpointGroupService
FileService portainer.FileService
@ -37,6 +38,7 @@ func NewHandler(bouncer *security.RequestBouncer, authorizeEndpointManagement bo
h := &Handler{
Router: mux.NewRouter(),
authorizeEndpointManagement: authorizeEndpointManagement,
requestBouncer: bouncer,
}
h.Handle("/endpoints",
@ -44,7 +46,7 @@ func NewHandler(bouncer *security.RequestBouncer, authorizeEndpointManagement bo
h.Handle("/endpoints",
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointList))).Methods(http.MethodGet)
h.Handle("/endpoints/{id}",
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointInspect))).Methods(http.MethodGet)
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointInspect))).Methods(http.MethodGet)
h.Handle("/endpoints/{id}",
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointUpdate))).Methods(http.MethodPut)
h.Handle("/endpoints/{id}/access",

View File

@ -320,7 +320,7 @@ paths:
summary: "Inspect an endpoint"
description: |
Retrieve details abount an endpoint.
**Access policy**: administrator
**Access policy**: restricted
operationId: "EndpointInspect"
produces:
- "application/json"

View File

@ -218,6 +218,30 @@ angular.module('portainer.docker')
return runningTasks;
};
})
.filter('containerswithstatus', function () {
'use strict';
return function (containers, status) {
var containersWithStatus = 0;
for (var i = 0; i < containers.length; i++) {
var container = containers[i];
if (container.Status === status) {
containersWithStatus++;
}
}
return containersWithStatus;
};
})
.filter('imagestotalsize', function () {
'use strict';
return function (images) {
var totalImageSize = 0;
for (var i = 0; i < images.length; i++) {
var item = images[i];
totalImageSize += item.VirtualSize;
}
return totalImageSize;
};
})
.filter('tasknodename', function () {
'use strict';
return function (nodeId, nodes) {

View File

@ -34,32 +34,37 @@
</div>
</div>
<div class="row" ng-if="!applicationState.endpoint.mode.agentProxy || applicationState.endpoint.mode.provider !== 'DOCKER_SWARM_MODE'">
<div class="row" ng-if="(!applicationState.endpoint.mode.agentProxy || applicationState.endpoint.mode.provider !== 'DOCKER_SWARM_MODE') && info && endpoint">
<div class="col-sm-12">
<rd-widget>
<rd-widget-header icon="fa-tachometer-alt" title-text="Node info"></rd-widget-header>
<rd-widget-header icon="fa-tachometer-alt" title-text="Endpoint info"></rd-widget-header>
<rd-widget-body classes="no-padding">
<table class="table">
<tbody>
<tr>
<td>Name</td>
<td>{{ infoData.Name }}</td>
<td>Endpoint</td>
<td>
{{ endpoint.Name }}
<span class="small text-muted space-left"><i class="fa fa-microchip"></i> {{ info.NCPU }}<i class="fa fa-memory space-left"></i> {{ info.MemTotal | humansize }}</span>
<span class="small text-muted"> - {{ info.Swarm && info.Swarm.NodeID !== '' ? 'Swarm' : 'Standalone' }} {{ info.ServerVersion }} <span ng-if="endpoint.Type === 2">+ <i class="fa fa-bolt" aria-hidden="true"></i> Agent</span></span>
</td>
</tr>
<tr>
<td>Docker version</td>
<td>{{ infoData.ServerVersion }}</td>
<td>URL</td>
<td>{{ endpoint.URL | stripprotocol }}</td>
</tr>
<tr>
<td>CPU</td>
<td>{{ infoData.NCPU }}</td>
</tr>
<tr>
<td>Memory</td>
<td>{{ infoData.MemTotal|humansize }}</td>
</tr>
<tr ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'">
<td>Node role</td>
<td>{{ infoData.Swarm.ControlAvailable ? 'Manager' : 'Worker' }}</td>
<td>Tags</td>
<td>
<span ng-if="endpoint.Tags.length === 0">
-
</span>
<span ng-if="endpoint.Tags.length > 0">
<span ng-repeat="tag in endpoint.Tags">
{{ tag }}{{ $last? '' : ', ' }}
</span>
</span>
</td>
</tr>
<tr ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && applicationState.endpoint.mode.role === 'MANAGER'">
<td colspan="2">
@ -102,7 +107,7 @@
</rd-widget>
</a>
</div>
<div class="col-xs-12 col-md-6">
<div class="col-xs-12 col-md-6" ng-if="containers">
<a ui-sref="docker.containers">
<rd-widget>
<rd-widget-body>
@ -110,16 +115,16 @@
<i class="fa fa-server"></i>
</div>
<div class="pull-right">
<div><i class="fa fa-heartbeat space-right green-icon"></i>{{ containerData.running }} running</div>
<div><i class="fa fa-heartbeat space-right red-icon"></i>{{ containerData.stopped }} stopped</div>
<div><i class="fa fa-heartbeat space-right green-icon"></i>{{ containers | containerswithstatus:'running' }} running</div>
<div><i class="fa fa-heartbeat space-right red-icon"></i>{{ containers | containerswithstatus:'stopped' }} stopped</div>
</div>
<div class="title">{{ containerData.total }}</div>
<div class="title">{{ containers.length }}</div>
<div class="comment">Containers</div>
</rd-widget-body>
</rd-widget>
</a>
</div>
<div class="col-xs-12 col-md-6">
<div class="col-xs-12 col-md-6" ng-if="images">
<a ui-sref="docker.images">
<rd-widget>
<rd-widget-body>
@ -127,9 +132,9 @@
<i class="fa fa-clone"></i>
</div>
<div class="pull-right">
<div><i class="fa fa-chart-pie space-right"></i>{{ imageData.size|humansize }}</div>
<div><i class="fa fa-chart-pie space-right"></i>{{ images | imagestotalsize | humansize }}</div>
</div>
<div class="title">{{ imageData.total }}</div>
<div class="title">{{ images.length }}</div>
<div class="comment">Images</div>
</rd-widget-body>
</rd-widget>
@ -142,7 +147,7 @@
<div class="widget-icon blue pull-left">
<i class="fa fa-cubes"></i>
</div>
<div class="title">{{ volumeData.total }}</div>
<div class="title">{{ volumeCount }}</div>
<div class="comment">Volumes</div>
</rd-widget-body>
</rd-widget>
@ -155,7 +160,7 @@
<div class="widget-icon blue pull-left">
<i class="fa fa-sitemap"></i>
</div>
<div class="title">{{ networkData.total }}</div>
<div class="title">{{ networkCount }}</div>
<div class="comment">Networks</div>
</rd-widget-body>
</rd-widget>

View File

@ -1,95 +1,33 @@
angular.module('portainer.docker')
.controller('DashboardController', ['$scope', '$q', 'Container', 'ContainerHelper', 'Image', 'Network', 'Volume', 'SystemService', 'ServiceService', 'StackService', 'Notifications', 'EndpointProvider',
function ($scope, $q, Container, ContainerHelper, Image, Network, Volume, SystemService, ServiceService, StackService, Notifications, EndpointProvider) {
$scope.containerData = {
total: 0
};
$scope.imageData = {
total: 0
};
$scope.networkData = {
total: 0
};
$scope.volumeData = {
total: 0
};
$scope.serviceCount = 0;
$scope.stackCount = 0;
function prepareContainerData(d) {
var running = 0;
var stopped = 0;
var containers = d;
for (var i = 0; i < containers.length; i++) {
var item = containers[i];
if (item.Status.indexOf('Up') !== -1) {
running += 1;
} else if (item.Status.indexOf('Exit') !== -1) {
stopped += 1;
}
}
$scope.containerData.running = running;
$scope.containerData.stopped = stopped;
$scope.containerData.total = containers.length;
}
function prepareImageData(d) {
var images = d;
var totalImageSize = 0;
for (var i = 0; i < images.length; i++) {
var item = images[i];
totalImageSize += item.VirtualSize;
}
$scope.imageData.total = images.length;
$scope.imageData.size = totalImageSize;
}
function prepareVolumeData(d) {
var volumes = d.Volumes;
if (volumes) {
$scope.volumeData.total = volumes.length;
}
}
function prepareNetworkData(d) {
var networks = d;
$scope.networkData.total = networks.length;
}
function prepareInfoData(d) {
var info = d;
$scope.infoData = info;
}
.controller('DashboardController', ['$scope', '$q', 'ContainerService', 'ImageService', 'NetworkService', 'VolumeService', 'SystemService', 'ServiceService', 'StackService', 'EndpointService', 'Notifications', 'EndpointProvider',
function ($scope, $q, ContainerService, ImageService, NetworkService, VolumeService, SystemService, ServiceService, StackService, EndpointService, Notifications, EndpointProvider) {
function initView() {
var endpointMode = $scope.applicationState.endpoint.mode;
var endpointId = EndpointProvider.endpointID();
$q.all([
Container.query({all: 1}).$promise,
Image.query({}).$promise,
Volume.query({}).$promise,
Network.query({}).$promise,
SystemService.info(),
endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER' ? ServiceService.services() : [],
StackService.stacks(
true,
endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER',
endpointId
)
]).then(function (d) {
prepareContainerData(d[0]);
prepareImageData(d[1]);
prepareVolumeData(d[2]);
prepareNetworkData(d[3]);
prepareInfoData(d[4]);
$scope.serviceCount = d[5].length;
$scope.stackCount = d[6].length;
}, function(e) {
Notifications.error('Failure', e, 'Unable to load dashboard data');
$q.all({
containers: ContainerService.containers(1),
images: ImageService.images(false),
volumes: VolumeService.volumes(),
networks: NetworkService.networks(true, true, true),
services: endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER' ? ServiceService.services() : [],
stacks: StackService.stacks(true, endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', endpointId),
info: SystemService.info(),
endpoint: EndpointService.endpoint(endpointId)
})
.then(function success(data) {
$scope.containers = data.containers;
$scope.images = data.images;
$scope.volumeCount = data.volumes.length;
$scope.networkCount = data.networks.length;
$scope.serviceCount = data.services.length;
$scope.stackCount = data.stacks.length;
$scope.info = data.info;
$scope.endpoint = data.endpoint;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to load dashboard data');
});
}