ENV |
-
+
{{ var|key: '=' }} |
{{ var|value: '=' }} |
diff --git a/app/components/image/imageController.js b/app/components/image/imageController.js
index fc663e23e..8514ff1bb 100644
--- a/app/components/image/imageController.js
+++ b/app/components/image/imageController.js
@@ -1,111 +1,109 @@
angular.module('image', [])
-.filter('onlylabel', function(){
- return function(tag){
- return tag.substr(tag.indexOf(":")+1);
+.controller('ImageController', ['$scope', '$stateParams', '$state', 'ImageService', 'Messages',
+function ($scope, $stateParams, $state, ImageService, Messages) {
+ $scope.config = {
+ Image: '',
+ Registry: ''
};
-})
-.controller('ImageController', ['$scope', '$stateParams', '$state', 'Image', 'ImageService', 'ImageHelper', 'Messages',
-function ($scope, $stateParams, $state, Image, ImageService, ImageHelper, Messages) {
- $scope.RepoTags = [];
- $scope.config = {
- Image: '',
- Registry: ''
- };
- // Get RepoTags from the /images/query endpoint instead of /image/json,
- // for backwards compatibility with Docker API versions older than 1.21
- function getRepoTags(imageId) {
- Image.query({}, function (d) {
- d.forEach(function(image) {
- if (image.Id === imageId && image.RepoTags[0] !== ':') {
- $scope.RepoTags = image.RepoTags;
- }
- });
- });
- }
+ $scope.tagImage = function() {
+ $('#loadingViewSpinner').show();
+ var image = $scope.config.Image;
+ var registry = $scope.config.Registry;
- $scope.tagImage = function() {
- $('#loadingViewSpinner').show();
- var image = $scope.config.Image;
- var registry = $scope.config.Registry;
- var imageConfig = ImageHelper.createImageConfigForCommit(image, registry);
- Image.tag({id: $stateParams.id, tag: imageConfig.tag, repo: imageConfig.repo}, function (d) {
- Messages.send('Image successfully tagged');
- $('#loadingViewSpinner').hide();
- $state.go('image', {id: $stateParams.id}, {reload: true});
- }, function(e) {
- $('#loadingViewSpinner').hide();
- Messages.error("Failure", e, "Unable to tag image");
- });
- };
+ ImageService.tagImage($stateParams.id, image, registry)
+ .then(function success(data) {
+ Messages.send('Image successfully tagged');
+ $state.go('image', {id: $stateParams.id}, {reload: true});
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, "Unable to tag image");
+ })
+ .finally(function final() {
+ $('#loadingViewSpinner').hide();
+ });
+ };
- $scope.pushImage = function(tag) {
- $('#loadingViewSpinner').show();
- Image.push({tag: tag}, function (d) {
- if (d[d.length-1].error) {
- Messages.error("Unable to push image", {}, d[d.length-1].error);
- } else {
- Messages.send('Image successfully pushed');
- }
- $('#loadingViewSpinner').hide();
- }, function (e) {
- $('#loadingViewSpinner').hide();
- Messages.error("Failure", e, "Unable to push image");
- });
- };
+ $scope.pushImage = function(tag) {
+ $('#loadingViewSpinner').show();
+ ImageService.pushImage(tag)
+ .then(function success() {
+ Messages.send('Image successfully pushed');
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, "Unable to push image tag");
+ })
+ .finally(function final() {
+ $('#loadingViewSpinner').hide();
+ });
+ };
- $scope.pullImage = function(tag) {
- var items = tag.split(":");
- var image = items[0];
- tag = items[1];
- $('#loadingViewSpinner').show();
- ImageService.pullImage({fromImage: image, tag: tag})
- .then(function success(data) {
- Messages.send('Image successfully pulled');
- })
- .catch(function error(error){
- Messages.error("Failure", error, "Unable to pull image");
- })
- .finally(function final() {
- $('#loadingViewSpinner').hide();
- });
- };
+ $scope.pullImage = function(tag) {
+ $('#loadingViewSpinner').show();
+ var image = $scope.config.Image;
+ var registry = $scope.config.Registry;
- $scope.removeImage = function (id) {
- $('#loadingViewSpinner').show();
- Image.remove({id: id}, function (d) {
- if (d[0].message) {
- $('#loadingViewSpinner').hide();
- Messages.error("Unable to remove image", {}, d[0].message);
- } else {
- // If last message key is 'Deleted' or if it's 'Untagged' and there is only one tag associated to the image
- // then assume the image is gone and send to images page
- if (d[d.length-1].Deleted || (d[d.length-1].Untagged && $scope.RepoTags.length === 1)) {
- Messages.send('Image successfully deleted');
- $state.go('images', {}, {reload: true});
- } else {
- Messages.send('Tag successfully deleted');
- $state.go('image', {id: $stateParams.id}, {reload: true});
- }
- }
- }, function (e) {
- $('#loadingViewSpinner').hide();
- Messages.error("Failure", e, 'Unable to remove image');
- });
- };
+ ImageService.pullImage(image, registry)
+ .then(function success(data) {
+ Messages.send('Image successfully pulled', image);
+ })
+ .catch(function error(err){
+ Messages.error("Failure", err, "Unable to pull image");
+ })
+ .finally(function final() {
+ $('#loadingViewSpinner').hide();
+ });
+ };
- $('#loadingViewSpinner').show();
- Image.get({id: $stateParams.id}, function (d) {
- $scope.image = d;
- if (d.RepoTags) {
- $scope.RepoTags = d.RepoTags;
- } else {
- getRepoTags(d.Id);
- }
- $('#loadingViewSpinner').hide();
- $scope.exposedPorts = d.ContainerConfig.ExposedPorts ? Object.keys(d.ContainerConfig.ExposedPorts) : [];
- $scope.volumes = d.ContainerConfig.Volumes ? Object.keys(d.ContainerConfig.Volumes) : [];
- }, function (e) {
- Messages.error("Failure", e, "Unable to retrieve image info");
- });
+ $scope.removeTag = function(id) {
+ $('#loadingViewSpinner').show();
+ ImageService.deleteImage(id, false)
+ .then(function success() {
+ if ($scope.image.RepoTags.length === 1) {
+ Messages.send('Image successfully deleted', id);
+ $state.go('images', {}, {reload: true});
+ } else {
+ Messages.send('Tag successfully deleted', id);
+ $state.go('image', {id: $stateParams.id}, {reload: true});
+ }
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, 'Unable to remove image');
+ })
+ .finally(function final() {
+ $('#loadingViewSpinner').hide();
+ });
+ };
+
+ $scope.removeImage = function (id) {
+ $('#loadingViewSpinner').show();
+ ImageService.deleteImage(id, false)
+ .then(function success() {
+ Messages.send('Image successfully deleted', id);
+ $state.go('images', {}, {reload: true});
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, 'Unable to remove image');
+ })
+ .finally(function final() {
+ $('#loadingViewSpinner').hide();
+ });
+ };
+
+ function retrieveImageDetails() {
+ $('#loadingViewSpinner').show();
+ ImageService.image($stateParams.id)
+ .then(function success(data) {
+ $scope.image = data;
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, "Unable to retrieve image details");
+ $state.go('images');
+ })
+ .finally(function final() {
+ $('#loadingViewSpinner').hide();
+ });
+ }
+
+ retrieveImageDetails();
}]);
diff --git a/app/components/images/imagesController.js b/app/components/images/imagesController.js
index 44752330e..350b77c2a 100644
--- a/app/components/images/imagesController.js
+++ b/app/components/images/imagesController.js
@@ -1,6 +1,6 @@
angular.module('images', [])
-.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'ImageHelper', 'Messages', 'Pagination', 'ModalService',
-function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, ModalService) {
+.controller('ImagesController', ['$scope', '$state', 'Config', 'ImageService', 'Messages', 'Pagination', 'ModalService',
+function ($scope, $state, Config, ImageService, Messages, Pagination, ModalService) {
$scope.state = {};
$scope.state.pagination_count = Pagination.getPaginationCount('images');
$scope.sortType = 'RepoTags';
@@ -42,20 +42,15 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, Moda
$('#pullImageSpinner').show();
var image = $scope.config.Image;
var registry = $scope.config.Registry;
- var imageConfig = ImageHelper.createImageConfigForContainer(image, registry);
- Image.create(imageConfig, function (data) {
- var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error');
- if (err) {
- var detail = data[data.length - 1];
- $('#pullImageSpinner').hide();
- Messages.error('Error', {}, detail.error);
- } else {
- $('#pullImageSpinner').hide();
- $state.reload();
- }
- }, function (e) {
+ ImageService.pullImage(image, registry)
+ .then(function success(data) {
+ $state.reload();
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, "Unable to pull image");
+ })
+ .finally(function final() {
$('#pullImageSpinner').hide();
- Messages.error("Failure", e, "Unable to pull image");
});
};
@@ -79,18 +74,16 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, Moda
angular.forEach($scope.images, function (i) {
if (i.Checked) {
counter = counter + 1;
- Image.remove({id: i.Id, force: force}, function (d) {
- if (d[0].message) {
- $('#loadImagesSpinner').hide();
- Messages.error("Unable to remove image", {}, d[0].message);
- } else {
- Messages.send("Image deleted", i.Id);
- var index = $scope.images.indexOf(i);
- $scope.images.splice(index, 1);
- }
- complete();
- }, function (e) {
- Messages.error("Failure", e, 'Unable to remove image');
+ ImageService.deleteImage(i.Id, force)
+ .then(function success(data) {
+ Messages.send("Image deleted", i.Id);
+ var index = $scope.images.indexOf(i);
+ $scope.images.splice(index, 1);
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, 'Unable to remove image');
+ })
+ .finally(function final() {
complete();
});
}
@@ -98,19 +91,19 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, Moda
};
function fetchImages() {
- Image.query({}, function (d) {
- $scope.images = d.map(function (item) {
- return new ImageViewModel(item);
- });
- $('#loadImagesSpinner').hide();
- }, function (e) {
- $('#loadImagesSpinner').hide();
- Messages.error("Failure", e, "Unable to retrieve images");
+ $('#loadImagesSpinner').show();
+ ImageService.images()
+ .then(function success(data) {
+ $scope.images = data;
+ })
+ .catch(function error(err) {
+ Messages.error("Failure", err, "Unable to retrieve images");
$scope.images = [];
+ })
+ .finally(function final() {
+ $('#loadImagesSpinner').hide();
});
}
- Config.$promise.then(function (c) {
- fetchImages();
- });
+ fetchImages();
}]);
diff --git a/app/components/templates/templatesController.js b/app/components/templates/templatesController.js
index 8d501d30c..1db8927af 100644
--- a/app/components/templates/templatesController.js
+++ b/app/components/templates/templatesController.js
@@ -45,14 +45,14 @@ function ($scope, $q, $state, $anchorScroll, Config, ContainerService, Container
volumeResourceControlQueries.push(ResourceControlService.setVolumeResourceControl(Authentication.getUserDetails().ID, volume.Name));
});
}
- TemplateService.updateContainerConfigurationWithVolumes(templateConfiguration.container, template, data);
+ TemplateService.updateContainerConfigurationWithVolumes(templateConfiguration, template, data);
return $q.all(volumeResourceControlQueries)
.then(function success() {
- return ImageService.pullImage(templateConfiguration.image);
+ return ImageService.pullImage(template.Image, template.Registry);
});
})
.then(function success(data) {
- return ContainerService.createAndStartContainer(templateConfiguration.container);
+ return ContainerService.createAndStartContainer(templateConfiguration);
})
.then(function success(data) {
Messages.send('Container Started', data.Id);
diff --git a/app/models/imageDetails.js b/app/models/imageDetails.js
new file mode 100644
index 000000000..df7da6183
--- /dev/null
+++ b/app/models/imageDetails.js
@@ -0,0 +1,19 @@
+function ImageDetailsViewModel(data) {
+ this.Id = data.Id;
+ this.Tag = data.Tag;
+ this.Parent = data.Parent;
+ this.Repository = data.Repository;
+ this.Created = data.Created;
+ this.Checked = false;
+ this.RepoTags = data.RepoTags;
+ this.VirtualSize = data.VirtualSize;
+ this.DockerVersion = data.DockerVersion;
+ this.Os = data.Os;
+ this.Architecture = data.Architecture;
+ this.Author = data.Author;
+ this.Command = data.ContainerConfig.Cmd;
+ this.Entrypoint = data.ContainerConfig.Entrypoint ? data.ContainerConfig.Entrypoint : '';
+ this.ExposedPorts = data.ContainerConfig.ExposedPorts ? Object.keys(data.ContainerConfig.ExposedPorts) : [];
+ this.Volumes = data.ContainerConfig.Volumes ? Object.keys(data.ContainerConfig.Volumes) : [];
+ this.Env = data.ContainerConfig.Env ? data.ContainerConfig.Env : [];
+}
diff --git a/app/services/imageService.js b/app/services/imageService.js
index bba649998..a8a29cac5 100644
--- a/app/services/imageService.js
+++ b/app/services/imageService.js
@@ -1,10 +1,43 @@
angular.module('portainer.services')
-.factory('ImageService', ['$q', 'Image', function ImageServiceFactory($q, Image) {
+.factory('ImageService', ['$q', 'Image', 'ImageHelper', function ImageServiceFactory($q, Image, ImageHelper) {
'use strict';
var service = {};
- service.pullImage = function(imageConfiguration) {
+ service.image = function(imageId) {
var deferred = $q.defer();
+ Image.get({id: imageId}).$promise
+ .then(function success(data) {
+ if (data.message) {
+ deferred.reject({ msg: data.message });
+ } else {
+ var image = new ImageDetailsViewModel(data);
+ deferred.resolve(image);
+ }
+ })
+ .catch(function error(err) {
+ deferred.reject({ msg: 'Unable to retrieve image details', err: err });
+ });
+ return deferred.promise;
+ };
+
+ service.images = function() {
+ var deferred = $q.defer();
+ Image.query({}).$promise
+ .then(function success(data) {
+ var images = data.map(function (item) {
+ return new ImageViewModel(item);
+ });
+ deferred.resolve(images);
+ })
+ .catch(function error(err) {
+ deferred.reject({ msg: 'Unable to retrieve images', err: err });
+ });
+ return deferred.promise;
+ };
+
+ service.pullImage = function(image, registry) {
+ var deferred = $q.defer();
+ var imageConfiguration = ImageHelper.createImageConfigForContainer(image, registry);
Image.create(imageConfiguration).$promise
.then(function success(data) {
var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error');
@@ -20,5 +53,43 @@ angular.module('portainer.services')
});
return deferred.promise;
};
+
+ service.tagImage = function(id, image, registry) {
+ var imageConfig = ImageHelper.createImageConfigForCommit(image, registry);
+ return Image.tag({id: id, tag: imageConfig.tag, repo: imageConfig.repo}).$promise;
+ };
+
+ service.deleteImage = function(id, forceRemoval) {
+ var deferred = $q.defer();
+ Image.remove({id: id, force: forceRemoval}).$promise
+ .then(function success(data) {
+ if (data[0].message) {
+ deferred.reject({ msg: data[0].message });
+ } else {
+ deferred.resolve();
+ }
+ })
+ .catch(function error(err) {
+ deferred.reject({ msg: 'Unable to remove image', err: err });
+ });
+ return deferred.promise;
+ };
+
+ service.pushImage = function(tag) {
+ var deferred = $q.defer();
+ Image.push({tag: tag}).$promise
+ .then(function success(data) {
+ if (data[data.length - 1].error) {
+ deferred.reject({ msg: data[data.length - 1].error });
+ } else {
+ deferred.resolve();
+ }
+ })
+ .catch(function error(err) {
+ deferred.reject({ msg: 'Unable to push image tag', err: err });
+ });
+ return deferred.promise;
+ };
+
return service;
}]);
diff --git a/app/services/messages.js b/app/services/messages.js
index 3caf63ba6..7ed10b87d 100644
--- a/app/services/messages.js
+++ b/app/services/messages.js
@@ -22,6 +22,8 @@ angular.module('portainer.services')
msg = e.message;
} else if (e.data && e.data.length > 0 && e.data[0].message) {
msg = e.data[0].message;
+ } else if (e.msg) {
+ msg = e.msg;
}
$.gritter.add({
title: $sanitize(title),
diff --git a/app/services/templateService.js b/app/services/templateService.js
index 79958eb1c..fb1c86414 100644
--- a/app/services/templateService.js
+++ b/app/services/templateService.js
@@ -21,17 +21,10 @@ angular.module('portainer.services')
};
service.createTemplateConfiguration = function(template, containerName, network, containerMapping) {
- var imageConfiguration = service.createImageConfiguration(template);
+ var imageConfiguration = ImageHelper.createImageConfigForContainer(template.Image, template.Registry);
var containerConfiguration = service.createContainerConfiguration(template, containerName, network, containerMapping);
containerConfiguration.Image = imageConfiguration.fromImage + ':' + imageConfiguration.tag;
- return {
- container: containerConfiguration,
- image: imageConfiguration
- };
- };
-
- service.createImageConfiguration = function(template) {
- return ImageHelper.createImageConfigForContainer(template.Image, template.Registry);
+ return containerConfiguration;
};
service.createContainerConfiguration = function(template, containerName, network, containerMapping) {
|