mirror of
https://github.com/portainer/portainer.git
synced 2025-07-19 21:39:40 +02:00
refactor(image): refactor the code used in image and image details controller (#705)
This commit is contained in:
parent
c2e63070e6
commit
24b51a7e87
8 changed files with 245 additions and 167 deletions
|
@ -7,7 +7,7 @@
|
||||||
</rd-header-content>
|
</rd-header-content>
|
||||||
</rd-header>
|
</rd-header>
|
||||||
|
|
||||||
<div class="row" ng-if="RepoTags.length > 0">
|
<div class="row" ng-if="image.RepoTags.length > 0">
|
||||||
<div class="col-lg-12 col-md-12 col-xs-12">
|
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||||
<rd-widget>
|
<rd-widget>
|
||||||
<rd-widget-header icon="fa fa-tags" title="Image tags"></rd-widget-header>
|
<rd-widget-header icon="fa fa-tags" title="Image tags"></rd-widget-header>
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="pull-left" ng-repeat="tag in RepoTags" style="display:table">
|
<div class="pull-left" ng-repeat="tag in image.RepoTags" style="display:table">
|
||||||
<div class="input-group col-md-1" style="padding:0 15px">
|
<div class="input-group col-md-1" style="padding:0 15px">
|
||||||
<span class="input-group-addon">{{ tag }}</span>
|
<span class="input-group-addon">{{ tag }}</span>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<a data-toggle="tooltip" class="btn btn-primary interactive" title="Pull from registry" ng-click="pullImage(tag)">
|
<a data-toggle="tooltip" class="btn btn-primary interactive" title="Pull from registry" ng-click="pullImage(tag)">
|
||||||
<span class="fa fa-download white-icon" aria-hidden="true"></span>
|
<span class="fa fa-download white-icon" aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
<a data-toggle="tooltip" class="btn btn-primary interactive" title="Remove tag" ng-click="removeImage(tag)">
|
<a data-toggle="tooltip" class="btn btn-primary interactive" title="Remove tag" ng-click="removeTag(tag)">
|
||||||
<span class="fa fa-trash-o white-icon" aria-hidden="true"></span>
|
<span class="fa fa-trash-o white-icon" aria-hidden="true"></span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -36,7 +36,9 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<span class="small text-muted">
|
<span class="small text-muted">
|
||||||
Note: you can click on the upload icon to push or on the download icon to pull an image and on the trash icon to delete a tag
|
Note: you can click on the upload icon <span class="fa fa-upload" aria-hidden="true"></span> to push an image
|
||||||
|
or on the download icon <span class="fa fa-download" aria-hidden="true"></span> to pull an image
|
||||||
|
or on the trash icon <span class="fa fa-trash-o" aria-hidden="true"></span> to delete a tag.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -133,33 +135,33 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>CMD</td>
|
<td>CMD</td>
|
||||||
<td><code>{{ image.ContainerConfig.Cmd|command }}</code></td>
|
<td><code>{{ image.Command|command }}</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="image.ContainerConfig.Entrypoint">
|
<tr ng-if="image.Entrypoint">
|
||||||
<td>ENTRYPOINT</td>
|
<td>ENTRYPOINT</td>
|
||||||
<td><code>{{ image.ContainerConfig.Entrypoint|command }}</code></td>
|
<td><code>{{ image.Entrypoint|command }}</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="image.ContainerConfig.ExposedPorts">
|
<tr ng-if="image.ExposedPorts.length > 0">
|
||||||
<td>EXPOSE</td>
|
<td>EXPOSE</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="label label-default space-right" ng-repeat="port in exposedPorts">
|
<span class="label label-default space-right" ng-repeat="port in image.ExposedPorts">
|
||||||
{{ port }}
|
{{ port }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="image.ContainerConfig.Volumes">
|
<tr ng-if="image.Volumes.length > 0">
|
||||||
<td>VOLUME</td>
|
<td>VOLUME</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="label label-default space-right" ng-repeat="volume in volumes">
|
<span class="label label-default space-right" ng-repeat="volume in image.Volumes">
|
||||||
{{ volume }}
|
{{ volume }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr ng-if="image.Env.length > 0">
|
||||||
<td>ENV</td>
|
<td>ENV</td>
|
||||||
<td>
|
<td>
|
||||||
<table class="table table-bordered table-condensed">
|
<table class="table table-bordered table-condensed">
|
||||||
<tr ng-repeat="var in image.ContainerConfig.Env">
|
<tr ng-repeat="var in image.Env">
|
||||||
<td>{{ var|key: '=' }}</td>
|
<td>{{ var|key: '=' }}</td>
|
||||||
<td>{{ var|value: '=' }}</td>
|
<td>{{ var|value: '=' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1,111 +1,109 @@
|
||||||
angular.module('image', [])
|
angular.module('image', [])
|
||||||
.filter('onlylabel', function(){
|
.controller('ImageController', ['$scope', '$stateParams', '$state', 'ImageService', 'Messages',
|
||||||
return function(tag){
|
function ($scope, $stateParams, $state, ImageService, Messages) {
|
||||||
return tag.substr(tag.indexOf(":")+1);
|
$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,
|
$scope.tagImage = function() {
|
||||||
// for backwards compatibility with Docker API versions older than 1.21
|
$('#loadingViewSpinner').show();
|
||||||
function getRepoTags(imageId) {
|
var image = $scope.config.Image;
|
||||||
Image.query({}, function (d) {
|
var registry = $scope.config.Registry;
|
||||||
d.forEach(function(image) {
|
|
||||||
if (image.Id === imageId && image.RepoTags[0] !== '<none>:<none>') {
|
|
||||||
$scope.RepoTags = image.RepoTags;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.tagImage = function() {
|
ImageService.tagImage($stateParams.id, image, registry)
|
||||||
$('#loadingViewSpinner').show();
|
.then(function success(data) {
|
||||||
var image = $scope.config.Image;
|
Messages.send('Image successfully tagged');
|
||||||
var registry = $scope.config.Registry;
|
$state.go('image', {id: $stateParams.id}, {reload: true});
|
||||||
var imageConfig = ImageHelper.createImageConfigForCommit(image, registry);
|
})
|
||||||
Image.tag({id: $stateParams.id, tag: imageConfig.tag, repo: imageConfig.repo}, function (d) {
|
.catch(function error(err) {
|
||||||
Messages.send('Image successfully tagged');
|
Messages.error("Failure", err, "Unable to tag image");
|
||||||
$('#loadingViewSpinner').hide();
|
})
|
||||||
$state.go('image', {id: $stateParams.id}, {reload: true});
|
.finally(function final() {
|
||||||
}, function(e) {
|
$('#loadingViewSpinner').hide();
|
||||||
$('#loadingViewSpinner').hide();
|
});
|
||||||
Messages.error("Failure", e, "Unable to tag image");
|
};
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.pushImage = function(tag) {
|
$scope.pushImage = function(tag) {
|
||||||
$('#loadingViewSpinner').show();
|
$('#loadingViewSpinner').show();
|
||||||
Image.push({tag: tag}, function (d) {
|
ImageService.pushImage(tag)
|
||||||
if (d[d.length-1].error) {
|
.then(function success() {
|
||||||
Messages.error("Unable to push image", {}, d[d.length-1].error);
|
Messages.send('Image successfully pushed');
|
||||||
} else {
|
})
|
||||||
Messages.send('Image successfully pushed');
|
.catch(function error(err) {
|
||||||
}
|
Messages.error("Failure", err, "Unable to push image tag");
|
||||||
$('#loadingViewSpinner').hide();
|
})
|
||||||
}, function (e) {
|
.finally(function final() {
|
||||||
$('#loadingViewSpinner').hide();
|
$('#loadingViewSpinner').hide();
|
||||||
Messages.error("Failure", e, "Unable to push image");
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
|
||||||
$scope.pullImage = function(tag) {
|
$scope.pullImage = function(tag) {
|
||||||
var items = tag.split(":");
|
$('#loadingViewSpinner').show();
|
||||||
var image = items[0];
|
var image = $scope.config.Image;
|
||||||
tag = items[1];
|
var registry = $scope.config.Registry;
|
||||||
$('#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.removeImage = function (id) {
|
ImageService.pullImage(image, registry)
|
||||||
$('#loadingViewSpinner').show();
|
.then(function success(data) {
|
||||||
Image.remove({id: id}, function (d) {
|
Messages.send('Image successfully pulled', image);
|
||||||
if (d[0].message) {
|
})
|
||||||
$('#loadingViewSpinner').hide();
|
.catch(function error(err){
|
||||||
Messages.error("Unable to remove image", {}, d[0].message);
|
Messages.error("Failure", err, "Unable to pull image");
|
||||||
} else {
|
})
|
||||||
// If last message key is 'Deleted' or if it's 'Untagged' and there is only one tag associated to the image
|
.finally(function final() {
|
||||||
// then assume the image is gone and send to images page
|
$('#loadingViewSpinner').hide();
|
||||||
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');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$('#loadingViewSpinner').show();
|
$scope.removeTag = function(id) {
|
||||||
Image.get({id: $stateParams.id}, function (d) {
|
$('#loadingViewSpinner').show();
|
||||||
$scope.image = d;
|
ImageService.deleteImage(id, false)
|
||||||
if (d.RepoTags) {
|
.then(function success() {
|
||||||
$scope.RepoTags = d.RepoTags;
|
if ($scope.image.RepoTags.length === 1) {
|
||||||
} else {
|
Messages.send('Image successfully deleted', id);
|
||||||
getRepoTags(d.Id);
|
$state.go('images', {}, {reload: true});
|
||||||
}
|
} else {
|
||||||
$('#loadingViewSpinner').hide();
|
Messages.send('Tag successfully deleted', id);
|
||||||
$scope.exposedPorts = d.ContainerConfig.ExposedPorts ? Object.keys(d.ContainerConfig.ExposedPorts) : [];
|
$state.go('image', {id: $stateParams.id}, {reload: true});
|
||||||
$scope.volumes = d.ContainerConfig.Volumes ? Object.keys(d.ContainerConfig.Volumes) : [];
|
}
|
||||||
}, function (e) {
|
})
|
||||||
Messages.error("Failure", e, "Unable to retrieve image info");
|
.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();
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('images', [])
|
angular.module('images', [])
|
||||||
.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'ImageHelper', 'Messages', 'Pagination', 'ModalService',
|
.controller('ImagesController', ['$scope', '$state', 'Config', 'ImageService', 'Messages', 'Pagination', 'ModalService',
|
||||||
function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, ModalService) {
|
function ($scope, $state, Config, ImageService, Messages, Pagination, ModalService) {
|
||||||
$scope.state = {};
|
$scope.state = {};
|
||||||
$scope.state.pagination_count = Pagination.getPaginationCount('images');
|
$scope.state.pagination_count = Pagination.getPaginationCount('images');
|
||||||
$scope.sortType = 'RepoTags';
|
$scope.sortType = 'RepoTags';
|
||||||
|
@ -42,20 +42,15 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, Moda
|
||||||
$('#pullImageSpinner').show();
|
$('#pullImageSpinner').show();
|
||||||
var image = $scope.config.Image;
|
var image = $scope.config.Image;
|
||||||
var registry = $scope.config.Registry;
|
var registry = $scope.config.Registry;
|
||||||
var imageConfig = ImageHelper.createImageConfigForContainer(image, registry);
|
ImageService.pullImage(image, registry)
|
||||||
Image.create(imageConfig, function (data) {
|
.then(function success(data) {
|
||||||
var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error');
|
$state.reload();
|
||||||
if (err) {
|
})
|
||||||
var detail = data[data.length - 1];
|
.catch(function error(err) {
|
||||||
$('#pullImageSpinner').hide();
|
Messages.error("Failure", err, "Unable to pull image");
|
||||||
Messages.error('Error', {}, detail.error);
|
})
|
||||||
} else {
|
.finally(function final() {
|
||||||
$('#pullImageSpinner').hide();
|
|
||||||
$state.reload();
|
|
||||||
}
|
|
||||||
}, function (e) {
|
|
||||||
$('#pullImageSpinner').hide();
|
$('#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) {
|
angular.forEach($scope.images, function (i) {
|
||||||
if (i.Checked) {
|
if (i.Checked) {
|
||||||
counter = counter + 1;
|
counter = counter + 1;
|
||||||
Image.remove({id: i.Id, force: force}, function (d) {
|
ImageService.deleteImage(i.Id, force)
|
||||||
if (d[0].message) {
|
.then(function success(data) {
|
||||||
$('#loadImagesSpinner').hide();
|
Messages.send("Image deleted", i.Id);
|
||||||
Messages.error("Unable to remove image", {}, d[0].message);
|
var index = $scope.images.indexOf(i);
|
||||||
} else {
|
$scope.images.splice(index, 1);
|
||||||
Messages.send("Image deleted", i.Id);
|
})
|
||||||
var index = $scope.images.indexOf(i);
|
.catch(function error(err) {
|
||||||
$scope.images.splice(index, 1);
|
Messages.error("Failure", err, 'Unable to remove image');
|
||||||
}
|
})
|
||||||
complete();
|
.finally(function final() {
|
||||||
}, function (e) {
|
|
||||||
Messages.error("Failure", e, 'Unable to remove image');
|
|
||||||
complete();
|
complete();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -98,19 +91,19 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, Moda
|
||||||
};
|
};
|
||||||
|
|
||||||
function fetchImages() {
|
function fetchImages() {
|
||||||
Image.query({}, function (d) {
|
$('#loadImagesSpinner').show();
|
||||||
$scope.images = d.map(function (item) {
|
ImageService.images()
|
||||||
return new ImageViewModel(item);
|
.then(function success(data) {
|
||||||
});
|
$scope.images = data;
|
||||||
$('#loadImagesSpinner').hide();
|
})
|
||||||
}, function (e) {
|
.catch(function error(err) {
|
||||||
$('#loadImagesSpinner').hide();
|
Messages.error("Failure", err, "Unable to retrieve images");
|
||||||
Messages.error("Failure", e, "Unable to retrieve images");
|
|
||||||
$scope.images = [];
|
$scope.images = [];
|
||||||
|
})
|
||||||
|
.finally(function final() {
|
||||||
|
$('#loadImagesSpinner').hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.$promise.then(function (c) {
|
fetchImages();
|
||||||
fetchImages();
|
|
||||||
});
|
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -45,14 +45,14 @@ function ($scope, $q, $state, $anchorScroll, Config, ContainerService, Container
|
||||||
volumeResourceControlQueries.push(ResourceControlService.setVolumeResourceControl(Authentication.getUserDetails().ID, volume.Name));
|
volumeResourceControlQueries.push(ResourceControlService.setVolumeResourceControl(Authentication.getUserDetails().ID, volume.Name));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TemplateService.updateContainerConfigurationWithVolumes(templateConfiguration.container, template, data);
|
TemplateService.updateContainerConfigurationWithVolumes(templateConfiguration, template, data);
|
||||||
return $q.all(volumeResourceControlQueries)
|
return $q.all(volumeResourceControlQueries)
|
||||||
.then(function success() {
|
.then(function success() {
|
||||||
return ImageService.pullImage(templateConfiguration.image);
|
return ImageService.pullImage(template.Image, template.Registry);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
return ContainerService.createAndStartContainer(templateConfiguration.container);
|
return ContainerService.createAndStartContainer(templateConfiguration);
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
Messages.send('Container Started', data.Id);
|
Messages.send('Container Started', data.Id);
|
||||||
|
|
19
app/models/imageDetails.js
Normal file
19
app/models/imageDetails.js
Normal file
|
@ -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 : [];
|
||||||
|
}
|
|
@ -1,10 +1,43 @@
|
||||||
angular.module('portainer.services')
|
angular.module('portainer.services')
|
||||||
.factory('ImageService', ['$q', 'Image', function ImageServiceFactory($q, Image) {
|
.factory('ImageService', ['$q', 'Image', 'ImageHelper', function ImageServiceFactory($q, Image, ImageHelper) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var service = {};
|
var service = {};
|
||||||
|
|
||||||
service.pullImage = function(imageConfiguration) {
|
service.image = function(imageId) {
|
||||||
var deferred = $q.defer();
|
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
|
Image.create(imageConfiguration).$promise
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error');
|
var err = data.length > 0 && data[data.length - 1].hasOwnProperty('error');
|
||||||
|
@ -20,5 +53,43 @@ angular.module('portainer.services')
|
||||||
});
|
});
|
||||||
return deferred.promise;
|
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;
|
return service;
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -22,6 +22,8 @@ angular.module('portainer.services')
|
||||||
msg = e.message;
|
msg = e.message;
|
||||||
} else if (e.data && e.data.length > 0 && e.data[0].message) {
|
} else if (e.data && e.data.length > 0 && e.data[0].message) {
|
||||||
msg = e.data[0].message;
|
msg = e.data[0].message;
|
||||||
|
} else if (e.msg) {
|
||||||
|
msg = e.msg;
|
||||||
}
|
}
|
||||||
$.gritter.add({
|
$.gritter.add({
|
||||||
title: $sanitize(title),
|
title: $sanitize(title),
|
||||||
|
|
|
@ -21,17 +21,10 @@ angular.module('portainer.services')
|
||||||
};
|
};
|
||||||
|
|
||||||
service.createTemplateConfiguration = function(template, containerName, network, containerMapping) {
|
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);
|
var containerConfiguration = service.createContainerConfiguration(template, containerName, network, containerMapping);
|
||||||
containerConfiguration.Image = imageConfiguration.fromImage + ':' + imageConfiguration.tag;
|
containerConfiguration.Image = imageConfiguration.fromImage + ':' + imageConfiguration.tag;
|
||||||
return {
|
return containerConfiguration;
|
||||||
container: containerConfiguration,
|
|
||||||
image: imageConfiguration
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
service.createImageConfiguration = function(template) {
|
|
||||||
return ImageHelper.createImageConfigForContainer(template.Image, template.Registry);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
service.createContainerConfiguration = function(template, containerName, network, containerMapping) {
|
service.createContainerConfiguration = function(template, containerName, network, containerMapping) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue