diff --git a/app/components/templates/templatesController.js b/app/components/templates/templatesController.js
index ca71e0ab9..015dc5198 100644
--- a/app/components/templates/templatesController.js
+++ b/app/components/templates/templatesController.js
@@ -1,6 +1,6 @@
angular.module('templates', [])
-.controller('TemplatesController', ['$scope', '$q', '$state', '$anchorScroll', 'Config', 'ContainerService', 'ImageService', 'NetworkService', 'TemplateService', 'TemplateHelper', 'VolumeService', 'Messages', 'Pagination',
-function ($scope, $q, $state, $anchorScroll, Config, ContainerService, ImageService, NetworkService, TemplateService, TemplateHelper, VolumeService, Messages, Pagination) {
+.controller('TemplatesController', ['$scope', '$q', '$state', '$anchorScroll', 'Config', 'ContainerService', 'ContainerHelper', 'ImageService', 'NetworkService', 'TemplateService', 'TemplateHelper', 'VolumeService', 'Messages', 'Pagination',
+function ($scope, $q, $state, $anchorScroll, Config, ContainerService, ContainerHelper, ImageService, NetworkService, TemplateService, TemplateHelper, VolumeService, Messages, Pagination) {
$scope.state = {
selectedTemplate: null,
showAdvancedOptions: false,
@@ -15,6 +15,14 @@ function ($scope, $q, $state, $anchorScroll, Config, ContainerService, ImageServ
Pagination.setPaginationCount('templates', $scope.state.pagination_count);
};
+ $scope.addVolume = function () {
+ $scope.state.selectedTemplate.Volumes.push({ containerPath: '', name: '', readOnly: false, type: 'auto' });
+ };
+
+ $scope.removeVolume = function(index) {
+ $scope.state.selectedTemplate.Volumes.splice(index, 1);
+ };
+
$scope.addPortBinding = function() {
$scope.state.selectedTemplate.Ports.push({ hostPort: '', containerPort: '', protocol: 'tcp' });
};
@@ -27,8 +35,9 @@ function ($scope, $q, $state, $anchorScroll, Config, ContainerService, ImageServ
$('#createContainerSpinner').show();
var template = $scope.state.selectedTemplate;
var templateConfiguration = createTemplateConfiguration(template);
+ var generatedVolumeCount = TemplateHelper.determineRequiredGeneratedVolumeCount(template.Volumes);
- VolumeService.createAutoGeneratedLocalVolumes(template.Volumes)
+ VolumeService.createXAutoGeneratedLocalVolumes(generatedVolumeCount)
.then(function success(data) {
TemplateService.updateContainerConfigurationWithVolumes(templateConfiguration.container, template, data);
return ImageService.pullImage(templateConfiguration.image);
@@ -108,12 +117,14 @@ function ($scope, $q, $state, $anchorScroll, Config, ContainerService, ImageServ
$q.all({
templates: TemplateService.getTemplates(),
containers: ContainerService.getContainers(0, c.hiddenLabels),
- networks: NetworkService.getNetworks()
+ networks: NetworkService.getNetworks(),
+ volumes: VolumeService.getVolumes()
})
.then(function success(data) {
$scope.templates = data.templates;
$scope.runningContainers = data.containers;
$scope.availableNetworks = filterNetworksBasedOnProvider(data.networks);
+ $scope.availableVolumes = data.volumes.Volumes;
})
.catch(function error(err) {
$scope.templates = [];
diff --git a/app/helpers/templateHelper.js b/app/helpers/templateHelper.js
index 39da37746..0df432495 100644
--- a/app/helpers/templateHelper.js
+++ b/app/helpers/templateHelper.js
@@ -66,5 +66,32 @@ angular.module('portainer.helpers')
return env;
};
+ helper.createVolumeBindings = function(volumes, generatedVolumesPile) {
+ volumes.forEach(function (volume) {
+ if (volume.containerPath) {
+ var binding;
+ if (volume.type === 'auto') {
+ binding = generatedVolumesPile.pop().Name + ':' + volume.containerPath;
+ } else if (volume.type !== 'auto' && volume.name) {
+ binding = volume.name + ':' + volume.containerPath;
+ }
+ if (volume.readOnly) {
+ binding += ':ro';
+ }
+ volume.binding = binding;
+ }
+ });
+ };
+
+ helper.determineRequiredGeneratedVolumeCount = function(volumes) {
+ var count = 0;
+ volumes.forEach(function (volume) {
+ if (volume.type === 'auto') {
+ ++count;
+ }
+ });
+ return count;
+ };
+
return helper;
}]);
diff --git a/app/models/template.js b/app/models/template.js
index 2849544d7..58c974bee 100644
--- a/app/models/template.js
+++ b/app/models/template.js
@@ -7,7 +7,16 @@ function TemplateViewModel(data) {
this.Command = data.command ? data.command : '';
this.Network = data.network ? data.network : '';
this.Env = data.env ? data.env : [];
- this.Volumes = data.volumes ? data.volumes : [];
+ this.Volumes = [];
+ if (data.volumes) {
+ this.Volumes = data.volumes.map(function (v) {
+ return {
+ readOnly: false,
+ containerPath: v,
+ type: 'auto'
+ };
+ });
+ }
this.Ports = [];
if (data.ports) {
this.Ports = data.ports.map(function (p) {
diff --git a/app/services/templateService.js b/app/services/templateService.js
index c63ee8731..2c861c428 100644
--- a/app/services/templateService.js
+++ b/app/services/templateService.js
@@ -47,10 +47,14 @@ angular.module('portainer.services')
return configuration;
};
- service.updateContainerConfigurationWithVolumes = function(configuration, template, createdVolumes) {
- createdVolumes.forEach(function (volume, idx) {
- configuration.Volumes[template.Volumes[idx]] = {};
- configuration.HostConfig.Binds.push(volume.Name + ':' + template.Volumes[idx]);
+ service.updateContainerConfigurationWithVolumes = function(configuration, template, generatedVolumesPile) {
+ var volumes = template.Volumes;
+ TemplateHelper.createVolumeBindings(volumes, generatedVolumesPile);
+ volumes.forEach(function (volume) {
+ if (volume.binding) {
+ configuration.Volumes[volume.containerPath] = {};
+ configuration.HostConfig.Binds.push(volume.binding);
+ }
});
};
diff --git a/app/services/volumeService.js b/app/services/volumeService.js
index ef3debd5b..d889ce493 100644
--- a/app/services/volumeService.js
+++ b/app/services/volumeService.js
@@ -3,6 +3,10 @@ angular.module('portainer.services')
'use strict';
var service = {};
+ service.getVolumes = function() {
+ return Volume.query({}).$promise;
+ };
+
function prepareVolumeQueries(template, containerConfig) {
var volumeQueries = [];
if (template.volumes) {
@@ -48,10 +52,11 @@ angular.module('portainer.services')
return $q.all(createVolumeQueries);
};
- service.createAutoGeneratedLocalVolumes = function (volumes) {
- var createVolumeQueries = volumes.map(function(volume) {
- return service.createVolume({});
- });
+ service.createXAutoGeneratedLocalVolumes = function (x) {
+ var createVolumeQueries = [];
+ for (var i = 0; i < x; i++) {
+ createVolumeQueries.push(service.createVolume({}));
+ }
return $q.all(createVolumeQueries);
};
diff --git a/bower.json b/bower.json
index a75b42cef..c4f0adc85 100644
--- a/bower.json
+++ b/bower.json
@@ -26,7 +26,7 @@
"Chart.js": "1.0.2",
"angular": "~1.5.0",
"angular-cookies": "~1.5.0",
- "angular-bootstrap": "~1.0.3",
+ "angular-bootstrap": "~2.5.0",
"angular-ui-router": "^0.2.15",
"angular-sanitize": "~1.5.0",
"angular-mocks": "~1.5.0",