def delete_stack( profile: Union[str, bool] = False, region: Union[str, bool] = False, wait: bool = False, iam: Union[str, bool] = False, ) -> None: """Handle deletion of the stack. Two situation, normal deletion and retained deletion. When the selected stack is already in a 'DELETE_FAILED' state, extra fzf operation would be triggered for user to select logical id to retain in order for deletion to be success. :param profile: use a different profile for this operation :type profile: Union[str, bool], optional :param region: use a different region for this operation :type region: Union[str, bool], optional :param wait: pause the function and wait for stack delete complete :type wait: bool, optional :param iam: specify a iam arn to delete this stack :type iam: Union[str, bool] """ cloudformation = Cloudformation(profile, region) cloudformation.set_stack() logical_id_list: List[str] = [] if cloudformation.stack_details["StackStatus"] == "DELETE_FAILED": header: str = "stack is in the failed state, specify any resource to skip during deletion" logical_id_list = cloudformation.get_stack_resources(empty_allow=True, header=header) cloudformation_args: Dict[str, Any] = { "StackName": cloudformation.stack_name } if logical_id_list: cloudformation_args["RetainResources"] = logical_id_list if iam and type(iam) == str: cloudformation_args["RoleARN"] = iam elif iam and type(iam) == bool: iam_instance = IAM(profile=cloudformation.profile) iam_instance.set_arns( header= "select a iam role with permissions to delete the current stack", service="cloudformation.amazonaws.com", ) if iam_instance.arns[0]: cloudformation_args["RoleARN"] = iam_instance.arns[0] if not get_confirmation("Are you sure you want to delete the stack '%s'?" % cloudformation.stack_name): sys.exit(1) cloudformation.client.delete_stack(**cloudformation_args) print("Stack deletion initiated") if wait: cloudformation.wait("stack_delete_complete", "Wating for stack to be deleted ...") print("Stack deleted")
def setUp(self): fileloader = FileLoader() config_path = Path(__file__).resolve().parent.joinpath( "../data/fzfaws.yml") fileloader.load_config_file(config_path=str(config_path)) self.iam = IAM() capturedOutput = io.StringIO() sys.stdout = capturedOutput
def test_constructor(self): self.assertEqual([""], self.iam.arns) self.assertEqual("default", self.iam.profile) self.assertEqual("us-east-1", self.iam.region) iam = IAM(profile="root", region="us-east-1") self.assertEqual("root", iam.profile) self.assertEqual("us-east-1", iam.region) self.assertEqual([""], self.iam.arns)
def _set_permissions(self, update: bool = False) -> None: """Set the iam user for the current stack. All operation permissions will be based on this iam role. Select None to stop using iam role and use current profile permissions. :param update: show previous values if true :type update: bool, optional """ print(80 * "-") iam = IAM(profile=self.cloudformation.profile) if not update: header = ( "choose an IAM role to explicitly define CloudFormation's permissions\n" ) header += "Note: only IAM role can be assumed by CloudFormation is listed" iam.set_arns(header=header, service="cloudformation.amazonaws.com") else: header = "select a role Choose an IAM role to explicitly define CloudFormation's permissions\n" header += "Original value: %s" % self.cloudformation.stack_details.get( "RoleARN") iam.set_arns(header=header, service="cloudformation.amazonaws.com") if iam.arns: self._extra_args["RoleARN"] = iam.arns[0]
class TestIAM(unittest.TestCase): def setUp(self): fileloader = FileLoader() config_path = Path(__file__).resolve().parent.joinpath( "../data/fzfaws.yml") fileloader.load_config_file(config_path=str(config_path)) self.iam = IAM() capturedOutput = io.StringIO() sys.stdout = capturedOutput def tearDown(self): sys.stdout = sys.__stdout__ def test_constructor(self): self.assertEqual([""], self.iam.arns) self.assertEqual("default", self.iam.profile) self.assertEqual("us-east-1", self.iam.region) iam = IAM(profile="root", region="us-east-1") self.assertEqual("root", iam.profile) self.assertEqual("us-east-1", iam.region) self.assertEqual([""], self.iam.arns) @patch.object(Paginator, "paginate") @patch.object(Pyfzf, "process_list") @patch.object(Pyfzf, "append_fzf") @patch.object(Pyfzf, "execute_fzf") def test_setarns(self, mocked_fzf_execute, mocked_fzf_append, mocked_fzf_list, mocked_result): mocked_result.return_value = [{ "Roles": [{ "Path": "/", "RoleName": "admincloudformaitontest", "RoleId": "AROAVQL5EWXLRDZGWYAU2", "Arn": "arn:aws:iam::111111:role/admincloudformaitontest", "CreateDate": "2010-09-09", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Sid": "", "Effect": "Allow", "Principal": { "Service": "cloudformation.amazonaws.com" }, "Action": "sts:AssumeRole", }], }, "Description": "Allows CloudFormation to create and manage AWS stacks and resources on your behalf.", "MaxSessionDuration": 3600, }] }] # general test mocked_fzf_execute.return_value = ( "arn:aws:iam::111111:role/admincloudformaitontest") self.iam.set_arns() self.assertEqual(self.iam.arns, ["arn:aws:iam::111111:role/admincloudformaitontest"]) mocked_fzf_append.assert_not_called() mocked_fzf_list.assert_called_with( [{ "Path": "/", "RoleName": "admincloudformaitontest", "RoleId": "AROAVQL5EWXLRDZGWYAU2", "Arn": "arn:aws:iam::111111:role/admincloudformaitontest", "CreateDate": "2010-09-09", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Sid": "", "Effect": "Allow", "Principal": { "Service": "cloudformation.amazonaws.com" }, "Action": "sts:AssumeRole", }], }, "Description": "Allows CloudFormation to create and manage AWS stacks and resources on your behalf.", "MaxSessionDuration": 3600, }], "RoleName", "Arn", ) # parameter test self.iam.set_arns(service="cloudformation.amazonaws.com") mocked_fzf_append.assert_called_with( "RoleName: admincloudformaitontest Arn: arn:aws:iam::111111:role/admincloudformaitontest" ) mocked_fzf_append.reset_mock() self.iam.set_arns(service="hello") mocked_fzf_append.assert_not_called() mocked_fzf_list.reset_mock() self.iam.set_arns(header="hello", empty_allow=True, multi_select=True) mocked_fzf_list.assert_called_once() mocked_fzf_execute.assert_called_with(empty_allow=True, header="hello", multi_select=True, print_col=4) self.iam.set_arns(arns="111111") self.assertEqual(self.iam.arns, ["111111"]) self.iam.set_arns(arns=["111111", "222222"]) self.assertEqual(self.iam.arns, ["111111", "222222"]) # empty result test self.iam.arns = [""] mocked_fzf_execute.reset_mock() mocked_fzf_append.reset_mock() mocked_result.return_value = [] mocked_fzf_execute.return_value = "" self.iam.set_arns(service="cloudformation.amazonaws.com") mocked_fzf_append.assert_not_called() mocked_fzf_execute.assert_called_once() self.assertEqual([""], self.iam.arns)