1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-06 06:15:22 +02:00

feat(stacks): add support for stack deploy (#1280)

This commit is contained in:
Anthony Lapenna 2017-10-15 19:24:40 +02:00 committed by GitHub
parent 80827935da
commit 587e2fa673
77 changed files with 3219 additions and 702 deletions

View file

@ -37,6 +37,13 @@
<portainer-tooltip message="Access control applied on a container created using a template is also applied on each volume associated to the container." position="bottom" style="margin-left: 2px;"></portainer-tooltip>
</td>
</tr>
<tr ng-if="$ctrl.resourceControl.Type === 6 && $ctrl.resourceType !== 'stack'">
<td colspan="2">
<i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 2px;"></i>
Access control on this resource is inherited from the following stack: {{ $ctrl.resourceControl.ResourceId }}
<portainer-tooltip message="Access control applied on a stack is also applied on each resource in the stack." position="bottom" style="margin-left: 2px;"></portainer-tooltip>
</td>
</tr>
<!-- authorized-users -->
<tr ng-if="$ctrl.resourceControl.UserAccesses.length > 0">
<td>Authorized users</td>
@ -54,7 +61,11 @@
</tr>
<!-- !authorized-teams -->
<!-- edit-ownership -->
<tr ng-if="!($ctrl.resourceControl.Type === 1 && $ctrl.resourceType === 'volume') && !($ctrl.resourceControl.Type === 2 && $ctrl.resourceType === 'container') && !$ctrl.state.editOwnership && ($ctrl.isAdmin || $ctrl.state.canEditOwnership)">
<tr ng-if="!($ctrl.resourceControl.Type === 1 && $ctrl.resourceType === 'volume')
&& !($ctrl.resourceControl.Type === 2 && $ctrl.resourceType === 'container')
&& !($ctrl.resourceControl.Type === 6 && $ctrl.resourceType !== 'stack')
&& !$ctrl.state.editOwnership
&& ($ctrl.isAdmin || $ctrl.state.canEditOwnership)">
<td colspan="2">
<a class="btn-outline-secondary" ng-click="$ctrl.state.editOwnership = true"><i class="fa fa-edit space-right" aria-hidden="true"></i>Change ownership</a>
</td>

View file

@ -0,0 +1,8 @@
angular.module('portainer').component('porServiceList', {
templateUrl: 'app/directives/serviceList/porServiceList.html',
controller: 'porServiceListController',
bindings: {
'services': '<',
'nodes': '<'
}
});

View file

@ -0,0 +1,98 @@
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-header icon="fa-list-alt" title="Associated services">
<div class="pull-right">
Items per page:
<select ng-model="$ctrl.state.pagination_count" ng-change="$ctrl.changePaginationCount()">
<option value="0">All</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</rd-widget-header>
<rd-widget-taskbar classes="col-sm-12">
<div class="pull-right">
<input type="text" id="filter" ng-model="$ctrl.state.filter" placeholder="Filter..." class="form-control input-sm" />
</div>
</rd-widget-taskbar>
<rd-widget-body classes="no-padding">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>
<a ng-click="$ctrl.order('Name')">
Name
<span ng-show="$ctrl.sortType === 'Name' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Name' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th>
<a ng-click="$ctrl.order('Image')">
Image
<span ng-show="$ctrl.sortType === 'Image' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Image' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th>
<a ng-click="$ctrl.order('Mode')">
Scheduling mode
<span ng-show="$ctrl.sortType === 'Mode' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Mode' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th>
<a ng-click="$ctrl.order('Ports')">
Published Ports
<span ng-show="$ctrl.sortType === 'Ports' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Ports' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th>
<a ng-click="$ctrl.order('UpdatedAt')">
Updated at
<span ng-show="$ctrl.sortType === 'UpdatedAt' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'UpdatedAt' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="service in $ctrl.services | filter:$ctrl.state.filter | orderBy:$ctrl.sortType:$ctrl.sortReverse | itemsPerPage:$ctrl.state.pagination_count" pagination-id="services_list">
<td><a ui-sref="service({id: service.Id})">{{ service.Name }}</a></td>
<td>{{ service.Image | hideshasum }}</td>
<td>
{{ service.Mode }}
<code data-toggle="tooltip" title="Replicas">{{ service.Tasks | runningtaskscount }}</code>
/
<code data-toggle="tooltip" title="Replicas">{{ service.Mode === 'replicated' ? service.Replicas : ($ctrl.nodes | availablenodecount) }}</code>
</td>
<td>
<a ng-if="service.Ports && service.Ports.length > 0" ng-repeat="p in service.Ports" class="image-tag" ng-href="http://{{$ctrl.state.publicURL}}:{{p.PublishedPort}}" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i> {{ p.PublishedPort }}:{{ p.TargetPort }}
</a>
<span ng-if="!service.Ports || service.Ports.length === 0" >-</span>
</td>
<td>
{{ service.UpdatedAt|getisodate }}
</td>
</tr>
<tr ng-if="!$ctrl.services">
<td colspan="5" class="text-center text-muted">Loading...</td>
</tr>
<tr ng-if="($ctrl.services | filter:$ctrl.state.filter | orderBy:$ctrl.sortType:$ctrl.sortReverse | itemsPerPage: $ctrl.state.pagination_count).length === 0">
<td colspan="5" class="text-center text-muted">No services available.</td>
</tr>
</tbody>
</table>
<div ng-if="$ctrl.services" class="pull-left pagination-controls">
<dir-pagination-controls pagination-id="services_list"></dir-pagination-controls >
</div>
</div>
</rd-widget-body>
<rd-widget>
</div>
</div>

View file

@ -0,0 +1,21 @@
angular.module('portainer')
.controller('porServiceListController', ['EndpointProvider', 'Pagination',
function (EndpointProvider, Pagination) {
var ctrl = this;
ctrl.state = {
pagination_count: Pagination.getPaginationCount('services_list'),
publicURL: EndpointProvider.endpointPublicURL()
};
ctrl.sortType = 'Name';
ctrl.sortReverse = false;
ctrl.order = function(sortType) {
ctrl.sortReverse = (ctrl.sortType === sortType) ? !ctrl.sortReverse : false;
ctrl.sortType = sortType;
};
ctrl.changePaginationCount = function() {
Pagination.setPaginationCount('services_list', ctrl.state.pagination_count);
};
}]);

View file

@ -0,0 +1,8 @@
angular.module('portainer').component('porTaskList', {
templateUrl: 'app/directives/taskList/porTaskList.html',
controller: 'porTaskListController',
bindings: {
'tasks': '<',
'nodes': '<'
}
});

View file

@ -0,0 +1,78 @@
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-header icon="fa-tasks" title="Associated tasks">
<div class="pull-right">
Items per page:
<select ng-model="$ctrl.state.pagination_count" ng-change="$ctrl.changePaginationCount()">
<option value="0">All</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</rd-widget-header>
<rd-widget-taskbar classes="col-sm-12">
<div class="pull-right">
<input type="text" id="filter" ng-model="$ctrl.state.filter" placeholder="Filter..." class="form-control input-sm" />
</div>
</rd-widget-taskbar>
<rd-widget-body classes="no-padding">
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>
<a ng-click="$ctrl.order('Status.State')">
Status
<span ng-show="$ctrl.sortType === 'Status.State' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Status.State' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th ng-if="service.Mode !== 'global'">
<a ng-click="$ctrl.order('Slot')">
Slot
<span ng-show="$ctrl.sortType === 'Slot' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Slot' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th>
<a ng-click="$ctrl.order('NodeId')">
Node
<span ng-show="$ctrl.sortType === 'NodeId' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'NodeId' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
<th>
<a ng-click="$ctrl.order('Updated')">
Last update
<span ng-show="$ctrl.sortType === 'Updated' && !$ctrl.sortReverse" class="glyphicon glyphicon-chevron-down"></span>
<span ng-show="$ctrl.sortType === 'Updated' && $ctrl.sortReverse" class="glyphicon glyphicon-chevron-up"></span>
</a>
</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="task in $ctrl.tasks | filter:$ctrl.state.filter | orderBy:$ctrl.sortType:$ctrl.sortReverse | itemsPerPage:$ctrl.state.pagination_count">
<td><a ui-sref="task({ id: task.Id })">{{ task.Id }}</a></td>
<td><span class="label label-{{ task.Status.State | taskstatusbadge }}">{{ task.Status.State }}</span></td>
<td>{{ task.Slot ? task.Slot : '-' }}</td>
<td>{{ task.NodeId | tasknodename: $ctrl.nodes }}</td>
<td>{{ task.Updated | getisodate }}</td>
</tr>
<tr ng-if="!$ctrl.tasks">
<td colspan="5" class="text-center text-muted">Loading...</td>
</tr>
<tr ng-if="($ctrl.tasks | filter:$ctrl.state.filter | orderBy:$ctrl.sortType:$ctrl.sortReverse | itemsPerPage: $ctrl.state.pagination_count).length === 0">
<td colspan="5" class="text-center text-muted">No tasks available.</td>
</tr>
</tbody>
</table>
<div class="pagination-controls">
<dir-pagination-controls></dir-pagination-controls>
</div>
</rd-widget-body>
</rd-widget>
</div>
</div>

View file

@ -0,0 +1,19 @@
angular.module('portainer')
.controller('porTaskListController', ['Pagination',
function (Pagination) {
var ctrl = this;
ctrl.state = {
pagination_count: Pagination.getPaginationCount('tasks_list')
};
ctrl.sortType = 'Updated';
ctrl.sortReverse = true;
ctrl.order = function(sortType) {
ctrl.sortReverse = (ctrl.sortType === sortType) ? !ctrl.sortReverse : false;
ctrl.sortType = sortType;
};
ctrl.changePaginationCount = function() {
Pagination.setPaginationCount('tasks_list', ctrl.state.pagination_count);
};
}]);