diff --git a/app/components/createService/createServiceController.js b/app/components/createService/createServiceController.js
index ab85f14ed..369c219cf 100644
--- a/app/components/createService/createServiceController.js
+++ b/app/components/createService/createServiceController.js
@@ -20,6 +20,7 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
Volumes: [],
Network: '',
ExtraNetworks: [],
+ HostsEntries: [],
Ports: [],
Parallelism: 1,
PlacementConstraints: [],
@@ -69,6 +70,14 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
$scope.formValues.ExtraNetworks.splice(index, 1);
};
+ $scope.addHostsEntry = function() {
+ $scope.formValues.HostsEntries.push({});
+ };
+
+ $scope.removeHostsEntry = function(index) {
+ $scope.formValues.HostsEntries.splice(index, 1);
+ };
+
$scope.addVolume = function() {
$scope.formValues.Volumes.push({ Source: '', Target: '', ReadOnly: false, Type: 'volume' });
};
@@ -244,6 +253,22 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
config.Networks = _.uniqWith(networks, _.isEqual);
}
+ function prepareHostsEntries(config, input) {
+ var hostsEntries = [];
+ if (input.HostsEntries) {
+ input.HostsEntries.forEach(function (host_ip) {
+ if (host_ip.value && host_ip.value.indexOf(':') && host_ip.value.split(':').length === 2) {
+ var keyVal = host_ip.value.split(':');
+ // Hosts file format, IP_address canonical_hostname
+ hostsEntries.push(keyVal[1] + ' ' + keyVal[0]);
+ }
+ });
+ if (hostsEntries.length > 0) {
+ config.TaskTemplate.ContainerSpec.Hosts = hostsEntries;
+ }
+ }
+ }
+
function prepareUpdateConfig(config, input) {
config.UpdateConfig = {
Parallelism: input.Parallelism || 0,
@@ -355,6 +380,7 @@ function ($q, $scope, $state, $timeout, Service, ServiceHelper, ConfigService, C
prepareLabelsConfig(config, input);
prepareVolumes(config, input);
prepareNetworks(config, input);
+ prepareHostsEntries(config, input);
prepareUpdateConfig(config, input);
prepareConfigConfig(config, input);
prepareSecretConfig(config, input);
diff --git a/app/components/createService/createservice.html b/app/components/createService/createservice.html
index 9a86ee73c..3f96b372c 100644
--- a/app/components/createService/createservice.html
+++ b/app/components/createService/createservice.html
@@ -308,6 +308,29 @@
+
+
+
diff --git a/app/components/service/includes/hosts.html b/app/components/service/includes/hosts.html
new file mode 100644
index 000000000..7d9ab78c7
--- /dev/null
+++ b/app/components/service/includes/hosts.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+ The Hosts file has no extra entries.
+
+
+
+
+
+
+
+
+
diff --git a/app/components/service/service.html b/app/components/service/service.html
index 4715f5323..b889131d8 100644
--- a/app/components/service/service.html
+++ b/app/components/service/service.html
@@ -152,6 +152,7 @@
Networks & ports
+
diff --git a/app/components/service/serviceController.js b/app/components/service/serviceController.js
index 45518e02b..05d6ee618 100644
--- a/app/components/service/serviceController.js
+++ b/app/components/service/serviceController.js
@@ -168,6 +168,22 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
}
};
+ $scope.addHostsEntry = function (service) {
+ if (!service.Hosts) {
+ service.Hosts = [];
+ }
+ service.Hosts.push({ hostname: '', ip: '' });
+ };
+ $scope.removeHostsEntry = function(service, index) {
+ var removedElement = service.Hosts.splice(index, 1);
+ if (removedElement !== null) {
+ updateServiceArray(service, 'Hosts', service.Hosts);
+ }
+ };
+ $scope.updateHostsEntry = function(service, entry) {
+ updateServiceArray(service, 'Hosts', service.Hosts);
+ };
+
$scope.cancelChanges = function cancelChanges(service, keys) {
if (keys) { // clean out the keys only from the list of modified keys
keys.forEach(function(key) {
@@ -203,7 +219,8 @@ function ($q, $scope, $transition$, $state, $location, $timeout, $anchorScroll,
config.TaskTemplate.ContainerSpec.Image = service.Image;
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) : [];
+
if (service.Mode === 'replicated') {
config.Mode.Replicated.Replicas = service.Replicas;
}
@@ -300,6 +317,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.Hosts = ServiceHelper.translateHostsEntriesToHostnameIP(service.Hosts);
}
function transformResources(service) {
diff --git a/app/helpers/serviceHelper.js b/app/helpers/serviceHelper.js
index b25def767..36e66bd3e 100644
--- a/app/helpers/serviceHelper.js
+++ b/app/helpers/serviceHelper.js
@@ -191,5 +191,31 @@ angular.module('portainer.helpers').factory('ServiceHelper', [function ServiceHe
return humanDuration;
};
+ helper.translateHostsEntriesToHostnameIP = function(entries) {
+ var ipHostEntries = [];
+ if (entries) {
+ entries.forEach(function(entry) {
+ if (entry.indexOf(' ') && entry.split(' ').length === 2) {
+ var keyValue = entry.split(' ');
+ ipHostEntries.push({ hostname: keyValue[1], ip: keyValue[0]});
+ }
+ });
+ }
+ return ipHostEntries;
+ };
+
+
+ helper.translateHostnameIPToHostsEntries = function(entries) {
+ var ipHostEntries = [];
+ if (entries) {
+ entries.forEach(function(entry) {
+ if (entry.ip && entry.hostname) {
+ ipHostEntries.push(entry.ip + ' ' + entry.hostname);
+ }
+ });
+ }
+ return ipHostEntries;
+ };
+
return helper;
}]);