From bc17f23c094bb17bd5abad24b0441b1eae987d37 Mon Sep 17 00:00:00 2001 From: itsconquest Date: Tue, 4 Feb 2020 18:23:09 +1300 Subject: [PATCH] feat(service-details): ability to manage networks --- app/docker/helpers/serviceHelper.js | 17 ++++++++ .../services/edit/includes/networks.html | 42 +++++++++++++++---- .../views/services/edit/serviceController.js | 32 +++++++++++--- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/app/docker/helpers/serviceHelper.js b/app/docker/helpers/serviceHelper.js index f9d2fb689..6f6fe6d79 100644 --- a/app/docker/helpers/serviceHelper.js +++ b/app/docker/helpers/serviceHelper.js @@ -1,4 +1,5 @@ import moment from 'moment'; +import _ from 'lodash-es'; angular.module('portainer.docker') .factory('ServiceHelper', [function ServiceHelperFactory() { @@ -21,6 +22,22 @@ angular.module('portainer.docker') tasks = otherServicesTasks; }; + function findAssociatedNetwork(serviceNetwork, networks) { + return _.find(networks, function(network) { + return network.Id === serviceNetwork.NetworkID; + }); + } + + helper.mapNetworkNameToServiceNetwork = function(service, networks) { + for (var i = 0; i < service.ServiceNetworks.length; i++) { + var serviceNetwork = service.ServiceNetworks[i]; + var network = findAssociatedNetwork(serviceNetwork, networks); + if (network) { + serviceNetwork.Name = network.Name; + } + } + }; + helper.serviceToConfig = function(service) { return { Name: service.Spec.Name, diff --git a/app/docker/views/services/edit/includes/networks.html b/app/docker/views/services/edit/includes/networks.html index 6fab8b638..0a4cba8b0 100644 --- a/app/docker/views/services/edit/includes/networks.html +++ b/app/docker/views/services/edit/includes/networks.html @@ -1,26 +1,52 @@
- -

This service is not connected to any networks.

-
- - +
+ Add a network: + + + add network + +
+

This service is not connected to any networks.

+
- + + - + +
IDNetwork IP addressActions
- {{ network.NetworkID }} + {{ network.Name }} {{ network.Addr }} + +
+ + +
diff --git a/app/docker/views/services/edit/serviceController.js b/app/docker/views/services/edit/serviceController.js index d2e33e271..95643ce2d 100644 --- a/app/docker/views/services/edit/serviceController.js +++ b/app/docker/views/services/edit/serviceController.js @@ -18,10 +18,11 @@ require('./includes/tasks.html') require('./includes/updateconfig.html') import { PorImageRegistryModel } from 'Docker/models/porImageRegistry'; +import _ from 'lodash-es'; angular.module('portainer.docker') -.controller('ServiceController', ['$q', '$scope', '$transition$', '$state', '$location', '$timeout', '$anchorScroll', 'ServiceService', 'ConfigService', 'ConfigHelper', 'SecretService', 'ImageService', 'SecretHelper', 'Service', 'ServiceHelper', 'LabelHelper', 'TaskService', 'NodeService', 'ContainerService', 'TaskHelper', 'Notifications', 'ModalService', 'PluginService', 'Authentication', 'SettingsService', 'VolumeService', 'ImageHelper', 'WebhookService', 'EndpointProvider', 'clipboard','WebhookHelper', -function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, ServiceService, ConfigService, ConfigHelper, SecretService, ImageService, SecretHelper, Service, ServiceHelper, LabelHelper, TaskService, NodeService, ContainerService, TaskHelper, Notifications, ModalService, PluginService, Authentication, SettingsService, VolumeService, ImageHelper, WebhookService, EndpointProvider, clipboard, WebhookHelper) { +.controller('ServiceController', ['$q', '$scope', '$transition$', '$state', '$location', '$timeout', '$anchorScroll', 'ServiceService', 'ConfigService', 'ConfigHelper', 'SecretService', 'ImageService', 'SecretHelper', 'Service', 'ServiceHelper', 'LabelHelper', 'TaskService', 'NodeService', 'NetworkService', 'ContainerService', 'TaskHelper', 'Notifications', 'ModalService', 'PluginService', 'Authentication', 'SettingsService', 'VolumeService', 'ImageHelper', 'WebhookService', 'EndpointProvider', 'clipboard','WebhookHelper', +function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, ServiceService, ConfigService, ConfigHelper, SecretService, ImageService, SecretHelper, Service, ServiceHelper, LabelHelper, TaskService, NodeService, NetworkService, ContainerService, TaskHelper, Notifications, ModalService, PluginService, Authentication, SettingsService, VolumeService, ImageHelper, WebhookService, EndpointProvider, clipboard, WebhookHelper) { $scope.state = { updateInProgress: false, @@ -167,7 +168,19 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, $scope.updatePlacementPreference = function(service) { updateServiceArray(service, 'ServicePreferences', service.ServicePreferences); }; - + $scope.addNetwork = function addNetwork(service, network) { + if (network && !_.find(service.ServiceNetworks, {'NetworkID': network.Id})) { + service.ServiceNetworks.push({NetworkID: network.Id}) + updateServiceArray(service, 'ServiceNetworks', service.ServiceNetworks); + ServiceHelper.mapNetworkNameToServiceNetwork(service, $scope.networks); + } + }; + $scope.removeNetwork = function removeNetwork(service, index) { + var removedElement = service.ServiceNetworks.splice(index, 1); + if (removedElement !== null) { + updateServiceArray(service, 'ServiceNetworks', service.ServiceNetworks); + } + }; $scope.addPublishedPort = function addPublishedPort(service) { if (!service.Ports) { service.Ports = []; @@ -297,7 +310,9 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, } else { config.TaskTemplate.ContainerSpec.Image = service.Image; } - + if ($scope.hasChanges(service, ["ServiceNetworks"])) { + config.TaskTemplate.Networks = _.map(service.ServiceNetworks, ({NetworkID}) => ({ Target: NetworkID})); + } config.TaskTemplate.ContainerSpec.Secrets = service.ServiceSecrets ? service.ServiceSecrets.map(SecretHelper.secretConfig) : []; config.TaskTemplate.ContainerSpec.Configs = service.ServiceConfigs ? service.ServiceConfigs.map(ConfigHelper.configConfig) : []; config.TaskTemplate.ContainerSpec.Hosts = service.Hosts ? ServiceHelper.translateHostnameIPToHostsEntries(service.Hosts) : []; @@ -508,6 +523,7 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, service.ServiceMounts = angular.copy(service.Mounts); service.ServiceConstraints = ServiceHelper.translateConstraintsToKeyValue(service.Constraints); service.ServicePreferences = ServiceHelper.translatePreferencesToKeyValue(service.Preferences); + service.ServiceNetworks = service.VirtualIPs ? angular.copy(service.VirtualIPs) : []; service.Hosts = ServiceHelper.translateHostsEntriesToHostnameIP(service.Hosts); } @@ -549,6 +565,8 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, tasks: TaskService.tasks({ service: [service.Name] }), containers: agentProxy ? ContainerService.containers() : [], nodes: NodeService.nodes(), + networks: NetworkService.networks(true, true, true), + availableNetworks: NetworkService.networks(true, true, true), secrets: apiVersion >= 1.25 ? SecretService.secrets() : [], configs: apiVersion >= 1.30 ? ConfigService.configs() : [], availableImages: ImageService.images(), @@ -566,7 +584,8 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, $scope.availableVolumes = data.volumes; $scope.allowBindMounts = data.settings.AllowBindMountsForRegularUsers; $scope.isAdmin = Authentication.isAdmin(); - + $scope.networks = data.networks; + $scope.availableNetworks = data.availableNetworks; if (data.webhooks.length > 0) { var webhook = data.webhooks[0]; $scope.WebhookExists = true; @@ -588,7 +607,8 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll, $scope.tasks = data.tasks; - + ServiceHelper.mapNetworkNameToServiceNetwork(service, data.networks); + // Set max cpu value var maxCpus = 0; for (var n in data.nodes) {