2019-03-21 05:46:49 +00:00
import _ from 'lodash-es' ;
2019-11-27 22:36:39 +00:00
import { PorImageRegistryModel } from 'Docker/models/porImageRegistry' ;
2023-02-14 08:19:41 +00:00
import { confirmImageExport } from '@/react/docker/images/common/ConfirmExportModal' ;
2023-05-21 10:16:15 +00:00
import { confirmDestructive } from '@@/modals/confirm' ;
2023-02-14 08:19:41 +00:00
import { buildConfirmButton } from '@@/modals/utils' ;
2019-03-21 05:46:49 +00:00
2020-04-10 21:54:53 +00:00
angular . module ( 'portainer.docker' ) . controller ( 'ImagesController' , [
'$scope' ,
'$state' ,
2021-03-24 18:27:32 +00:00
'Authentication' ,
2020-04-10 21:54:53 +00:00
'ImageService' ,
'Notifications' ,
'HttpRequestHelper' ,
'FileSaver' ,
'Blob' ,
2021-03-24 18:27:32 +00:00
'endpoint' ,
2023-05-21 10:16:15 +00:00
'$async' ,
2023-07-13 07:47:20 +00:00
function ( $scope , $state , Authentication , ImageService , Notifications , HttpRequestHelper , FileSaver , Blob , endpoint ) {
2021-03-24 18:27:32 +00:00
$scope . endpoint = endpoint ;
$scope . isAdmin = Authentication . isAdmin ( ) ;
2020-04-10 21:54:53 +00:00
$scope . state = {
actionInProgress : false ,
exportInProgress : false ,
2021-03-24 18:27:32 +00:00
pullRateValid : false ,
2020-04-10 21:54:53 +00:00
} ;
$scope . formValues = {
RegistryModel : new PorImageRegistryModel ( ) ,
NodeName : null ,
} ;
$scope . pullImage = function ( ) {
const registryModel = $scope . formValues . RegistryModel ;
var nodeName = $scope . formValues . NodeName ;
HttpRequestHelper . setPortainerAgentTargetHeader ( nodeName ) ;
$scope . state . actionInProgress = true ;
ImageService . pullImage ( registryModel , false )
2021-07-23 20:51:34 +00:00
. then ( function success ( data ) {
var err = data [ data . length - 1 ] . errorDetail ;
if ( err ) {
return Notifications . error ( 'Failure' , err , 'Unable to pull image' ) ;
}
2020-04-10 21:54:53 +00:00
Notifications . success ( 'Image successfully pulled' , registryModel . Image ) ;
$state . reload ( ) ;
} )
. catch ( function error ( err ) {
Notifications . error ( 'Failure' , err , 'Unable to pull image' ) ;
} )
. finally ( function final ( ) {
$scope . state . actionInProgress = false ;
} ) ;
} ;
2023-07-13 07:47:20 +00:00
function confirmImageForceRemoval ( ) {
return confirmDestructive ( {
title : 'Are you sure?' ,
2023-08-19 16:19:02 +00:00
message :
"Forcing removal of an image will remove it even if it's used by stopped containers, and delete all associated tags. Are you sure you want to remove the selected image(s)?" ,
2023-07-13 07:47:20 +00:00
confirmButton : buildConfirmButton ( 'Remove the image' , 'danger' ) ,
} ) ;
}
2023-05-21 10:16:15 +00:00
2023-07-13 07:47:20 +00:00
function confirmRegularRemove ( ) {
return confirmDestructive ( {
title : 'Are you sure?' ,
2023-08-19 16:19:02 +00:00
message : 'Removing an image will also delete all associated tags. Are you sure you want to remove the selected image(s)?' ,
2023-07-13 07:47:20 +00:00
confirmButton : buildConfirmButton ( 'Remove the image' , 'danger' ) ,
2018-07-26 13:09:48 +00:00
} ) ;
2023-05-21 10:16:15 +00:00
}
2023-07-13 07:47:20 +00:00
$scope . confirmRemovalAction = async function ( selectedItems , force ) {
const confirmed = await ( force ? confirmImageForceRemoval ( ) : confirmRegularRemove ( ) ) ;
2023-05-21 10:16:15 +00:00
2023-07-13 07:47:20 +00:00
if ( ! confirmed ) {
return ;
}
2023-05-21 10:16:15 +00:00
2023-07-13 07:47:20 +00:00
$scope . removeAction ( selectedItems , force ) ;
} ;
2020-04-10 21:54:53 +00:00
function isAuthorizedToDownload ( selectedItems ) {
for ( var i = 0 ; i < selectedItems . length ; i ++ ) {
var image = selectedItems [ i ] ;
var untagged = _ . find ( image . RepoTags , function ( item ) {
return item . indexOf ( '<none>' ) > - 1 ;
} ) ;
2018-07-26 13:09:48 +00:00
2020-04-10 21:54:53 +00:00
if ( untagged ) {
Notifications . warning ( '' , 'Cannot download a untagged image' ) ;
return false ;
}
}
if ( _ . uniqBy ( selectedItems , 'NodeName' ) . length > 1 ) {
Notifications . warning ( '' , 'Cannot download images from different nodes at the same time' ) ;
2019-03-21 05:46:49 +00:00
return false ;
2018-07-26 13:09:48 +00:00
}
2020-04-10 21:54:53 +00:00
return true ;
2018-07-26 13:09:48 +00:00
}
2020-04-10 21:54:53 +00:00
function exportImages ( images ) {
HttpRequestHelper . setPortainerAgentTargetHeader ( images [ 0 ] . NodeName ) ;
$scope . state . exportInProgress = true ;
ImageService . downloadImages ( images )
. then ( function success ( data ) {
var downloadData = new Blob ( [ data . file ] , { type : 'application/x-tar' } ) ;
FileSaver . saveAs ( downloadData , 'images.tar' ) ;
2022-08-10 05:07:35 +00:00
Notifications . success ( 'Success' , 'Image(s) successfully downloaded' ) ;
2020-04-10 21:54:53 +00:00
} )
. catch ( function error ( err ) {
Notifications . error ( 'Failure' , err , 'Unable to download image(s)' ) ;
} )
. finally ( function final ( ) {
$scope . state . exportInProgress = false ;
} ) ;
2018-07-26 13:09:48 +00:00
}
2020-04-10 21:54:53 +00:00
$scope . downloadAction = function ( selectedItems ) {
if ( ! isAuthorizedToDownload ( selectedItems ) ) {
return ;
}
2023-02-14 08:19:41 +00:00
confirmImageExport ( function ( confirmed ) {
2020-04-10 21:54:53 +00:00
if ( ! confirmed ) {
return ;
2017-12-06 11:04:02 +00:00
}
2020-04-10 21:54:53 +00:00
exportImages ( selectedItems ) ;
} ) ;
} ;
$scope . removeAction = function ( selectedItems , force ) {
var actionCount = selectedItems . length ;
angular . forEach ( selectedItems , function ( image ) {
HttpRequestHelper . setPortainerAgentTargetHeader ( image . NodeName ) ;
ImageService . deleteImage ( image . Id , force )
. then ( function success ( ) {
Notifications . success ( 'Image successfully removed' , image . Id ) ;
var index = $scope . images . indexOf ( image ) ;
$scope . images . splice ( index , 1 ) ;
} )
. catch ( function error ( err ) {
Notifications . error ( 'Failure' , err , 'Unable to remove image' ) ;
} )
. finally ( function final ( ) {
-- actionCount ;
if ( actionCount === 0 ) {
$state . reload ( ) ;
}
} ) ;
2017-12-06 11:04:02 +00:00
} ) ;
2020-04-10 21:54:53 +00:00
} ;
$scope . getImages = getImages ;
function getImages ( ) {
ImageService . images ( true )
. then ( function success ( data ) {
$scope . images = data ;
} )
. catch ( function error ( err ) {
Notifications . error ( 'Failure' , err , 'Unable to retrieve images' ) ;
$scope . images = [ ] ;
} ) ;
}
2021-03-24 18:27:32 +00:00
$scope . setPullImageValidity = setPullImageValidity ;
function setPullImageValidity ( validity ) {
$scope . state . pullRateValid = validity ;
}
2020-04-10 21:54:53 +00:00
function initView ( ) {
getImages ( ) ;
}
initView ( ) ;
} ,
] ) ;