mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 07:15:23 +02:00
feat(stacks): support compose v2.0 stack (#1963)
This commit is contained in:
parent
ef15cd30eb
commit
e3d564325b
174 changed files with 7898 additions and 5849 deletions
|
@ -496,7 +496,7 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
|
|||
|
||||
$q.all({
|
||||
volumes: VolumeService.volumes(),
|
||||
networks: NetworkService.networks(true, true, false, false),
|
||||
networks: NetworkService.networks(true, true, false),
|
||||
secrets: apiVersion >= 1.25 ? SecretService.secrets() : [],
|
||||
configs: apiVersion >= 1.30 ? ConfigService.configs() : [],
|
||||
nodes: NodeService.nodes(),
|
||||
|
|
|
@ -7,18 +7,19 @@
|
|||
<rd-header-content>Services</rd-header-content>
|
||||
</rd-header>
|
||||
|
||||
<div class="row">
|
||||
<div class="row" ng-if="services">
|
||||
<div class="col-sm-12">
|
||||
<services-datatable
|
||||
title-text="Services" title-icon="fa-list-alt"
|
||||
dataset="services" table-key="services"
|
||||
order-by="Name" show-text-filter="true"
|
||||
nodes="nodes"
|
||||
agent-proxy="applicationState.endpoint.mode.agentProxy"
|
||||
show-ownership-column="applicationState.application.authentication"
|
||||
remove-action="removeAction"
|
||||
scale-action="scaleAction"
|
||||
force-update-action="forceUpdateAction"
|
||||
public-url="state.publicURL"
|
||||
show-force-update-button="applicationState.endpoint.apiVersion >= 1.25"
|
||||
show-update-action="applicationState.endpoint.apiVersion >= 1.25"
|
||||
show-task-logs-button="applicationState.endpoint.apiVersion >= 1.30"
|
||||
show-add-action="true"
|
||||
show-stack-column="true"
|
||||
></services-datatable>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,109 +1,36 @@
|
|||
angular.module('portainer.docker')
|
||||
.controller('ServicesController', ['$q', '$scope', '$state', 'Service', 'ServiceService', 'ServiceHelper', 'Notifications', 'Task', 'Node', 'ModalService', 'EndpointProvider',
|
||||
function ($q, $scope, $state, Service, ServiceService, ServiceHelper, Notifications, Task, Node, ModalService, EndpointProvider) {
|
||||
|
||||
$scope.state = {
|
||||
publicURL: EndpointProvider.endpointPublicURL()
|
||||
};
|
||||
|
||||
$scope.scaleAction = function scaleService(service) {
|
||||
var config = ServiceHelper.serviceToConfig(service.Model);
|
||||
config.Mode.Replicated.Replicas = service.Replicas;
|
||||
ServiceService.update(service, config)
|
||||
.then(function success(data) {
|
||||
Notifications.success('Service successfully scaled', 'New replica count: ' + service.Replicas);
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to scale service');
|
||||
service.Scale = false;
|
||||
service.Replicas = service.ReplicaCount;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.forceUpdateAction = function(selectedItems) {
|
||||
ModalService.confirmServiceForceUpdate(
|
||||
'Do you want to force update of selected service(s)? All the tasks associated to the selected service(s) will be recreated.',
|
||||
function onConfirm(confirmed) {
|
||||
if(!confirmed) { return; }
|
||||
forceUpdateServices(selectedItems);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
function forceUpdateServices(services) {
|
||||
var actionCount = services.length;
|
||||
angular.forEach(services, function (service) {
|
||||
var config = ServiceHelper.serviceToConfig(service.Model);
|
||||
// As explained in https://github.com/docker/swarmkit/issues/2364 ForceUpdate can accept a random
|
||||
// value or an increment of the counter value to force an update.
|
||||
config.TaskTemplate.ForceUpdate++;
|
||||
ServiceService.update(service, config)
|
||||
.then(function success(data) {
|
||||
Notifications.success('Service successfully updated', service.Name);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to force update service', service.Name);
|
||||
})
|
||||
.finally(function final() {
|
||||
--actionCount;
|
||||
if (actionCount === 0) {
|
||||
$state.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$scope.removeAction = function(selectedItems) {
|
||||
ModalService.confirmDeletion(
|
||||
'Do you want to remove the selected service(s)? All the containers associated to the selected service(s) will be removed too.',
|
||||
function onConfirm(confirmed) {
|
||||
if(!confirmed) { return; }
|
||||
removeServices(selectedItems);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
function removeServices(services) {
|
||||
var actionCount = services.length;
|
||||
angular.forEach(services, function (service) {
|
||||
ServiceService.remove(service)
|
||||
.then(function success() {
|
||||
Notifications.success('Service successfully removed', service.Name);
|
||||
var index = $scope.services.indexOf(service);
|
||||
$scope.services.splice(index, 1);
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to remove service');
|
||||
})
|
||||
.finally(function final() {
|
||||
--actionCount;
|
||||
if (actionCount === 0) {
|
||||
$state.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
.controller('ServicesController', ['$q', '$scope', 'ServiceService', 'ServiceHelper', 'Notifications', 'TaskService', 'TaskHelper', 'NodeService', 'ContainerService',
|
||||
function ($q, $scope, ServiceService, ServiceHelper, Notifications, TaskService, TaskHelper, NodeService, ContainerService) {
|
||||
|
||||
function initView() {
|
||||
var agentProxy = $scope.applicationState.endpoint.mode.agentProxy;
|
||||
|
||||
$q.all({
|
||||
services: Service.query({}).$promise,
|
||||
tasks: Task.query({filters: {'desired-state': ['running','accepted']}}).$promise,
|
||||
nodes: Node.query({}).$promise
|
||||
services: ServiceService.services(),
|
||||
tasks: TaskService.tasks(),
|
||||
containers: agentProxy ? ContainerService.containers(1) : [],
|
||||
nodes: NodeService.nodes()
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.services = data.services.map(function (service) {
|
||||
var runningTasks = data.tasks.filter(function (task) {
|
||||
return task.ServiceID === service.ID && task.Status.State === 'running';
|
||||
});
|
||||
var allTasks = data.tasks.filter(function (task) {
|
||||
return task.ServiceID === service.ID;
|
||||
});
|
||||
var taskNodes = data.nodes.filter(function (node) {
|
||||
return node.Spec.Availability === 'active' && node.Status.State === 'ready';
|
||||
});
|
||||
return new ServiceViewModel(service, runningTasks, allTasks, taskNodes);
|
||||
});
|
||||
var services = data.services;
|
||||
var tasks = data.tasks;
|
||||
|
||||
if (agentProxy) {
|
||||
var containers = data.containers;
|
||||
for (var j = 0; j < tasks.length; j++) {
|
||||
var task = tasks[j];
|
||||
TaskHelper.associateContainerToTask(task, containers);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < services.length; i++) {
|
||||
var service = services[i];
|
||||
ServiceHelper.associateTasksToService(service, tasks);
|
||||
}
|
||||
|
||||
$scope.nodes = data.nodes;
|
||||
$scope.tasks = tasks;
|
||||
$scope.services = services;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
$scope.services = [];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue