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' ;
2024-05-16 02:34:50 +00:00
import { processItemsInBatches } from '@/react/common/processItemsInBatches' ;
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 ;
$scope . state . actionInProgress = true ;
2024-06-10 18:54:31 +00:00
ImageService . pullImage ( registryModel , nodeName )
. then ( function success ( ) {
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-10-03 12:55:23 +00:00
/ * *
*
* @ param { Array < import ( '@/react/docker/images/queries/useImages' ) . ImagesListResponse > } selectedItems
* @ param { boolean } force
* /
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
2023-10-03 12:55:23 +00:00
/ * *
*
* @ param { Array < import ( '@/react/docker/images/queries/useImages' ) . ImagesListResponse > } selectedItems
* /
2020-04-10 21:54:53 +00:00
function isAuthorizedToDownload ( selectedItems ) {
for ( var i = 0 ; i < selectedItems . length ; i ++ ) {
var image = selectedItems [ i ] ;
2023-10-03 12:55:23 +00:00
var untagged = _ . find ( image . tags , function ( item ) {
2020-04-10 21:54:53 +00:00
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
}
2023-10-03 12:55:23 +00:00
/ * *
*
* @ param { Array < import ( '@/react/docker/images/queries/useImages' ) . ImagesListResponse > } images
* /
2020-04-10 21:54:53 +00:00
function exportImages ( images ) {
2023-10-03 12:55:23 +00:00
HttpRequestHelper . setPortainerAgentTargetHeader ( images [ 0 ] . nodeName ) ;
2020-04-10 21:54:53 +00:00
$scope . state . exportInProgress = true ;
ImageService . downloadImages ( images )
. then ( function success ( data ) {
2024-09-23 19:55:45 +00:00
var downloadData = new Blob ( [ data ] , { type : 'application/x-tar' } ) ;
2020-04-10 21:54:53 +00:00
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
}
2023-10-03 12:55:23 +00:00
/ * *
*
* @ param { Array < import ( '@/react/docker/images/queries/useImages' ) . ImagesListResponse > } selectedItems
* /
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 ) ;
} ) ;
} ;
2023-10-03 12:55:23 +00:00
$scope . removeAction = removeAction ;
/ * *
*
* @ param { Array < import ( '@/react/docker/images/queries/useImages' ) . ImagesListResponse > } selectedItems
* @ param { boolean } force
* /
2024-05-16 02:34:50 +00:00
async function removeAction ( selectedItems , force ) {
async function doRemove ( image ) {
2023-10-03 12:55:23 +00:00
HttpRequestHelper . setPortainerAgentTargetHeader ( image . nodeName ) ;
2024-05-16 02:34:50 +00:00
return ImageService . deleteImage ( image . id , force )
2020-04-10 21:54:53 +00:00
. then ( function success ( ) {
2023-10-03 12:55:23 +00:00
Notifications . success ( 'Image successfully removed' , image . id ) ;
2020-04-10 21:54:53 +00:00
} )
. catch ( function error ( err ) {
Notifications . error ( 'Failure' , err , 'Unable to remove image' ) ;
} ) ;
2024-05-16 02:34:50 +00:00
}
await processItemsInBatches ( selectedItems , doRemove ) ;
$state . reload ( ) ;
2020-04-10 21:54:53 +00:00
}
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
} ,
] ) ;