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} 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) return response.JSON(w, endpoint)
} }

View File

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

View File

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

View File

@ -218,6 +218,30 @@ angular.module('portainer.docker')
return runningTasks; 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 () { .filter('tasknodename', function () {
'use strict'; 'use strict';
return function (nodeId, nodes) { return function (nodeId, nodes) {

View File

@ -34,32 +34,37 @@
</div> </div>
</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"> <div class="col-sm-12">
<rd-widget> <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"> <rd-widget-body classes="no-padding">
<table class="table"> <table class="table">
<tbody> <tbody>
<tr> <tr>
<td>Name</td> <td>Endpoint</td>
<td>{{ infoData.Name }}</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>
<tr> <tr>
<td>Docker version</td> <td>URL</td>
<td>{{ infoData.ServerVersion }}</td> <td>{{ endpoint.URL | stripprotocol }}</td>
</tr> </tr>
<tr> <tr>
<td>CPU</td> <td>Tags</td>
<td>{{ infoData.NCPU }}</td> <td>
</tr> <span ng-if="endpoint.Tags.length === 0">
<tr> -
<td>Memory</td> </span>
<td>{{ infoData.MemTotal|humansize }}</td> <span ng-if="endpoint.Tags.length > 0">
</tr> <span ng-repeat="tag in endpoint.Tags">
<tr ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'"> {{ tag }}{{ $last? '' : ', ' }}
<td>Node role</td> </span>
<td>{{ infoData.Swarm.ControlAvailable ? 'Manager' : 'Worker' }}</td> </span>
</td>
</tr> </tr>
<tr ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && applicationState.endpoint.mode.role === 'MANAGER'"> <tr ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && applicationState.endpoint.mode.role === 'MANAGER'">
<td colspan="2"> <td colspan="2">
@ -102,7 +107,7 @@
</rd-widget> </rd-widget>
</a> </a>
</div> </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"> <a ui-sref="docker.containers">
<rd-widget> <rd-widget>
<rd-widget-body> <rd-widget-body>
@ -110,16 +115,16 @@
<i class="fa fa-server"></i> <i class="fa fa-server"></i>
</div> </div>
<div class="pull-right"> <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 green-icon"></i>{{ containers | containerswithstatus:'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 red-icon"></i>{{ containers | containerswithstatus:'stopped' }} stopped</div>
</div> </div>
<div class="title">{{ containerData.total }}</div> <div class="title">{{ containers.length }}</div>
<div class="comment">Containers</div> <div class="comment">Containers</div>
</rd-widget-body> </rd-widget-body>
</rd-widget> </rd-widget>
</a> </a>
</div> </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"> <a ui-sref="docker.images">
<rd-widget> <rd-widget>
<rd-widget-body> <rd-widget-body>
@ -127,9 +132,9 @@
<i class="fa fa-clone"></i> <i class="fa fa-clone"></i>
</div> </div>
<div class="pull-right"> <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>
<div class="title">{{ imageData.total }}</div> <div class="title">{{ images.length }}</div>
<div class="comment">Images</div> <div class="comment">Images</div>
</rd-widget-body> </rd-widget-body>
</rd-widget> </rd-widget>
@ -142,7 +147,7 @@
<div class="widget-icon blue pull-left"> <div class="widget-icon blue pull-left">
<i class="fa fa-cubes"></i> <i class="fa fa-cubes"></i>
</div> </div>
<div class="title">{{ volumeData.total }}</div> <div class="title">{{ volumeCount }}</div>
<div class="comment">Volumes</div> <div class="comment">Volumes</div>
</rd-widget-body> </rd-widget-body>
</rd-widget> </rd-widget>
@ -155,7 +160,7 @@
<div class="widget-icon blue pull-left"> <div class="widget-icon blue pull-left">
<i class="fa fa-sitemap"></i> <i class="fa fa-sitemap"></i>
</div> </div>
<div class="title">{{ networkData.total }}</div> <div class="title">{{ networkCount }}</div>
<div class="comment">Networks</div> <div class="comment">Networks</div>
</rd-widget-body> </rd-widget-body>
</rd-widget> </rd-widget>

View File

@ -1,95 +1,33 @@
angular.module('portainer.docker') angular.module('portainer.docker')
.controller('DashboardController', ['$scope', '$q', 'Container', 'ContainerHelper', 'Image', 'Network', 'Volume', 'SystemService', 'ServiceService', 'StackService', 'Notifications', 'EndpointProvider', .controller('DashboardController', ['$scope', '$q', 'ContainerService', 'ImageService', 'NetworkService', 'VolumeService', 'SystemService', 'ServiceService', 'StackService', 'EndpointService', 'Notifications', 'EndpointProvider',
function ($scope, $q, Container, ContainerHelper, Image, Network, Volume, SystemService, ServiceService, StackService, Notifications, EndpointProvider) { function ($scope, $q, ContainerService, ImageService, NetworkService, VolumeService, SystemService, ServiceService, StackService, EndpointService, 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;
}
function initView() { function initView() {
var endpointMode = $scope.applicationState.endpoint.mode; var endpointMode = $scope.applicationState.endpoint.mode;
var endpointId = EndpointProvider.endpointID(); var endpointId = EndpointProvider.endpointID();
$q.all([ $q.all({
Container.query({all: 1}).$promise, containers: ContainerService.containers(1),
Image.query({}).$promise, images: ImageService.images(false),
Volume.query({}).$promise, volumes: VolumeService.volumes(),
Network.query({}).$promise, networks: NetworkService.networks(true, true, true),
SystemService.info(), services: endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER' ? ServiceService.services() : [],
endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER' ? ServiceService.services() : [], stacks: StackService.stacks(true, endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', endpointId),
StackService.stacks( info: SystemService.info(),
true, endpoint: EndpointService.endpoint(endpointId)
endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER', })
endpointId .then(function success(data) {
) $scope.containers = data.containers;
]).then(function (d) { $scope.images = data.images;
prepareContainerData(d[0]); $scope.volumeCount = data.volumes.length;
prepareImageData(d[1]); $scope.networkCount = data.networks.length;
prepareVolumeData(d[2]); $scope.serviceCount = data.services.length;
prepareNetworkData(d[3]); $scope.stackCount = data.stacks.length;
prepareInfoData(d[4]); $scope.info = data.info;
$scope.serviceCount = d[5].length; $scope.endpoint = data.endpoint;
$scope.stackCount = d[6].length; })
}, function(e) { .catch(function error(err) {
Notifications.error('Failure', e, 'Unable to load dashboard data'); Notifications.error('Failure', err, 'Unable to load dashboard data');
}); });
} }