@@ -158,10 +158,11 @@ def check(self) -> bool:
158158 f"{ ref_name } replication into the migration account in progress!"
159159 )
160160 else :
161- if machine .get ("replica" ):
161+ replica : str = machine .get ("replica" )
162+ if replica :
162163 machine_status += 1
163164 print (
164- f"{ ref_name } has been launched in the migration account"
165+ f"{ ref_name } has been launched in the migration account: { replica } "
165166 )
166167 else :
167168 print (
@@ -197,7 +198,7 @@ def update_encryption_key(self, kms_id: str) -> bool:
197198
198199 """
199200 print (
200- f"Updating Encryption Key - Name: ({ self .project_name } ) -KMS ID: ({ kms_id } ) - Dry Run: ({ self .dry_run } )"
201+ f"Updating Encryption Key - Name: ({ self .project_name } ) - KMS ID: ({ kms_id } ) - Dry Run: ({ self .dry_run } )"
201202 )
202203
203204 machines_response : Response = self .api .api_call (
@@ -774,6 +775,82 @@ def gen_terraform(
774775 template = template + drive_template
775776 return template
776777
778+ def terminate (self ) -> bool :
779+ """Terminate the launched machine(s).
780+
781+ Returns:
782+ bool: Whether cleanup was successful.
783+
784+ """
785+ machines_response : Response = self .api .api_call (
786+ f"projects/{ self .project_id } /machines"
787+ )
788+ success = True
789+ for _machine in self .target_machines :
790+ for machine in json .loads (machines_response .text ).get ("items" , []):
791+ source_props : Dict [str , Any ] = machine .get ("sourceProperties" , {})
792+ ref_name : str = source_props .get ("name" ) or source_props .get (
793+ "machineCloudId" , "NONE"
794+ )
795+ if _machine == source_props .get (
796+ "name" , "NONE"
797+ ) or _machine == source_props .get ("machineCloudId" , "NONE" ):
798+ replica : str = machine .get ("replica" )
799+ if replica :
800+ f"{ ref_name } has a launched machine: { replica } . Terminating."
801+ data_dict : Dict [str , Any ] = {}
802+ data_dict ["replicaIDs" ] = [replica ]
803+
804+ delete_response : Response = self .api .api_call (
805+ path = f"projects/{ self .project_id } /replicas" ,
806+ method = "delete" ,
807+ data = json .dumps (data_dict ),
808+ )
809+ if delete_response .status_code != 202 :
810+ print (
811+ f"Response code: { delete_response .status_code } \n { ref_name } replica { replica } did not terminate.\n { delete_response .text } "
812+ )
813+ success = False
814+ else :
815+ print (
816+ f"Terminated { ref_name } \n { json .loads (delete_response .text )} "
817+ )
818+ else :
819+ print (f"{ ref_name } does not have a launched machine" )
820+ success = False
821+
822+ return success
823+
824+ def delete_image (self , image_id : str ) -> bool :
825+ """Remove the AMI and snapshots.
826+
827+ Args:
828+ image_id (str): The AWS AMI to be deleted.
829+
830+ Returns:
831+ bool: Whether the AMI deletion was requested successfully.
832+
833+ """
834+ print ("Loading EC2 resource for region: " , AWS_REGION )
835+ _ec2_res = boto3 .resource ("ec2" , AWS_REGION )
836+
837+ try :
838+ # Access the image that needs to be deleted
839+ image = _ec2_res .Image (image_id )
840+
841+ # grab device mappings before deregistering
842+ devices : List [Any ] = image .block_device_mappings
843+ image .deregister ()
844+ for device in devices :
845+ if "Ebs" in device :
846+ snap = _ec2_res .Snapshot (device ["Ebs" ].get ("SnapshotId" ))
847+ snap .delete ()
848+ except Exception as e :
849+ print (f"Failed. AMI does not exist? { str (e )} " )
850+ return False
851+
852+ return True
853+
777854
778855def main () -> None :
779856 """Define the main entry method for the CLI."""
0 commit comments