mirror of https://github.com/portainer/portainer
Merge branch 'feat-1807-service-network-management' of github.com:portainer/portainer into develop
commit
e4254cb634
|
@ -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,
|
||||
|
|
|
@ -1,26 +1,52 @@
|
|||
<div id="service-network-specs">
|
||||
<rd-widget>
|
||||
<rd-widget-header icon="fa-tasks" title-text="Networks"></rd-widget-header>
|
||||
<rd-widget-body ng-if="!service.VirtualIPs || service.VirtualIPs.length === 0">
|
||||
<p>This service is not connected to any networks.</p>
|
||||
</rd-widget-body>
|
||||
<rd-widget-body ng-if="service.VirtualIPs && service.VirtualIPs.length > 0" classes="no-padding">
|
||||
<table class="table" >
|
||||
<div class="form-inline" style="padding: 10px;" authorization="DockerServiceUpdate">
|
||||
Add a network:
|
||||
<select class="form-control" ng-options="network.Name for network in availableNetworks | orderBy: 'Id'" ng-model="newNetwork">
|
||||
<option selected disabled hidden value="">Select a network</option>
|
||||
</select>
|
||||
<a class="btn btn-default btn-sm" ng-click="addNetwork(service, newNetwork)">
|
||||
<i class="fa fa-plus-circle" aria-hidden="true"></i> add network
|
||||
</a>
|
||||
</div>
|
||||
<p style="padding: 10px;" ng-if="!service.ServiceNetworks || service.ServiceNetworks.length === 0">This service is not connected to any networks.</p>
|
||||
<table class="table" style="margin-top: 5px;" ng-if="service.ServiceNetworks && service.ServiceNetworks.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Network</th>
|
||||
<th>IP address</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="network in service.VirtualIPs">
|
||||
<tr ng-repeat="network in service.ServiceNetworks">
|
||||
<td>
|
||||
<a ui-sref="docker.networks.network({id: network.NetworkID})">{{ network.NetworkID }}</a>
|
||||
<a ui-sref="docker.networks.network({id: network.NetworkID})">{{ network.Name }}</a>
|
||||
</td>
|
||||
<td>{{ network.Addr }}</td>
|
||||
<td authorization="DockerServiceUpdate">
|
||||
<button type="button" class="btn btn-xs btn-danger" ng-click="removeNetwork(service, $index)" ng-disabled="isUpdating">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i> Remove network
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</rd-widget-body>
|
||||
<rd-widget-footer>
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="btn-group" role="group">
|
||||
<button type="submit" class="btn btn-primary btn-sm" ng-disabled="!hasChanges(service, ['ServiceNetworks'])" ng-click="updateService(service)">Apply changes</button>
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a ng-click="cancelChanges(service, ['ServiceNetworks'])"">Reset changes</a></li>
|
||||
<li><a ng-click="cancelChanges(service)">Reset all changes</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</rd-widget-footer>
|
||||
</rd-widget>
|
||||
</div>
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue