def test_fetch_stack_events(self, n_evnt, _): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() stack.client = mock.Mock() class Paging: @staticmethod def paginate(**kwargs): return [{ "StackEvents": [{ "StackId": "arn:aws:cloudformation:us-east-1:" "123456789012:stack/" "SampleStack/e722ae60-fe62-11e8-9a0e-0ae8cc519968" }] }] stack.client.get_paginator.return_value = Paging() stack._fetch_stack_events() stack.client.get_paginator.assert_called_once() self.assertEqual(len(stack._events), 1)
def test_fetch_stack_resources(self, mock_template, _, __): region = make_test_region_obj("us-west-2") m_template = make_test_template() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() stack.client = mock.Mock() class Paging: @staticmethod def paginate(**kwargs): return [ { "StackResourceSummaries": [ { "StackId": "arn:aws:cloudformation:us-east-1:" "123456789012:stack/" "SampleStack/e722ae60-fe62-11e8-9a0e-0ae8cc519968" } ] } ] stack.client.get_paginator.return_value = Paging() stack._fetch_stack_resources() stack.client.get_paginator.assert_called_once() self.assertEqual(len(stack._resources), 1)
def test_refresh(self, mock_template, m_kids, m_res, m_eve, m_prop, _): region = make_test_region_obj("us-west-2") m_template = make_test_template() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() m_prop.reset_mock() stack.refresh() m_prop.assert_called_once() m_res.assert_not_called() m_eve.assert_not_called() m_kids.assert_not_called() m_prop.reset_mock() stack.refresh(properties=False, events=True) m_eve.assert_called_once() m_res.assert_not_called() m_prop.assert_not_called() m_kids.assert_not_called() m_eve.reset_mock() stack.refresh(properties=False, resources=True) m_res.assert_called_once() m_eve.assert_not_called() m_prop.assert_not_called() m_kids.assert_not_called() m_res.reset_mock() stack.refresh(properties=False, children=True) m_kids.assert_called_once() m_res.assert_not_called() m_prop.assert_not_called() m_res.assert_not_called()
def test_descentants(self, m_evnts, __): region = make_test_region_obj("us-west-2") region.client = mock_client_method test_proj = (Path(__file__).parent / "./data/nested-fail").resolve() c = Config.create(project_config_path=test_proj / ".taskcat.yml", project_root=test_proj) templates = c.get_templates() stack = Stack.create(region, "stack_name", templates["taskcat-json"]) stack._timer.cancel() child = event_template.copy() grandchild = event_template.copy() child["PhysicalResourceId"] = ( "arn:aws:cloudformation:us-east-1:123456789012:" "stack/Child/e722ae60-fe62-11e8-9a0e-0ae8cc519969") child["ResourceProperties"] = ( '{"TemplateURL": "https://test.s3.amazonaws.com/templates/' 'test.template_inner.yaml"}') grandchild["PhysicalResourceId"] = ( "arn:aws:cloudformation:us-east-1:123456789012:stack/GrandChild/" "e722ae60-fe62-11e8-9a0e-0ae8cc519970") grandchild["ResourceProperties"] = ( '{"TemplateURL": "https://test.s3.amazonaws.com/templates/' 'test.template_middle.yaml"}') m_evnts.return_value = Events([Event(child), Event(grandchild)]) desc = stack.descendants() self.assertEqual(len(desc), 2)
def test_create_with_role_arn(self, mock_template, m_s3_url_maker): region = make_test_region_obj("us-west-2", role_name="ExampleRole") mock_cfn_client = mock_client_method("cloudformation") region.client = mock_cfn_client region.client.return_value = mock_cfn_client template = make_test_template() stack = Stack.create(region=region, stack_name="stack_name", template=template) self.assertIsInstance(stack._timer, Timer) # disabled due to a concurrency issue with the tests # self.assertEqual(stack._timer.is_alive(), True) stack._timer.cancel() m_s3_url_maker.assert_called_once() self.assertNotEqual(template, stack.template) mock_template.assert_called_once() region.client.create_stack.assert_called_with( Capabilities=[ "CAPABILITY_IAM", "CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND", ], DisableRollback=True, Parameters=[], RoleARN="arn:aws:iam::123456789012:role/ExampleRole", StackName="stack_name", Tags=[], TemplateURL="blah", )
def _import_stacks_per_client(clients, uid, project_name, tests): # pylint: disable=too-many-locals stacks = Stacks() client, region = clients for page in client.get_paginator("describe_stacks").paginate(): for stack_props in page["Stacks"]: if stack_props.get("ParentId"): continue match = False project = "" test = "" for tag in stack_props["Tags"]: k, v = (tag["Key"], tag["Value"]) if k == "taskcat-id" and v == uid.hex: match = True elif k == "taskcat-test-name" and v in tests: test = v elif k == "taskcat-project-name" and v == project_name: project = v if match and test and project: stack = Stack.import_existing(stack_props, tests[test].template, region[0], test, uid) stacks.append(stack) return stacks
def __init__( self, package: str, aws_profile: str = "default", region="default", _stack_type="package", ): """ :param package: installed package to delete, can be an install name or uuid :param aws_profile: aws profile to use for deletion :param region: region to delete from, default will use aws cli configured default """ LOG.warning("delete is in alpha feature, use with caution") boto3_cache = Boto3Cache() if region == "default": region = boto3_cache.get_default_region(aws_profile) if isinstance(region, str): region = [region] stacks = Stacker.list_stacks([aws_profile], region) jobs = [] for stack in stacks: name = stack.get("taskcat-installer", stack["taskcat-project-name"]) job = { "name": name, "project_name": stack["taskcat-project-name"], "test_name": stack["taskcat-test-name"], "taskcat_id": stack["taskcat-id"].hex, "region": stack["region"], "type": "package" if stack.get("taskcat-installer") else "test", "stack_id": stack["stack-id"], } if _stack_type == job["type"]: if package in [job["name"], job["taskcat_id"], "ALL"]: jobs.append(job) # TODO: concurrency and wait for complete for job in jobs: client = boto3_cache.client("cloudformation", profile=aws_profile, region=job["region"]) Stack.delete(client=client, stack_id=job["stack_id"])
def test_delete(self, mock_template, _, __): region = make_test_region_obj("us-west-2") m_template = make_test_template() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() stack.client = mock.Mock() stack.refresh.reset_mock() stack.delete(client=stack.client, stack_id=stack.id) stack.client.delete_stack.assert_called_once()
def test_create(self, mock_template, m_s3_url_maker): region = make_test_region_obj("us-west-2") template = make_test_template() stack = Stack.create(region, "stack_name", template) self.assertIsInstance(stack._timer, Timer) # disabled due to a concurrency issue with the tests # self.assertEqual(stack._timer.is_alive(), True) stack._timer.cancel() m_s3_url_maker.assert_called_once() self.assertNotEquals(template, stack.template) mock_template.assert_called_once()
def test_create(self, m_s3_url_maker): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) self.assertIsInstance(stack._timer, Timer) self.assertEqual(stack._timer.is_alive(), True) stack._timer.cancel() m_s3_url_maker.assert_called_once()
def test_delete(self, _, __): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() stack.client = mock.Mock() stack.refresh.reset_mock() stack.delete() stack.client.delete_stack.assert_called_once() stack.refresh.assert_called_once()
def test_idempotent_properties(self, _): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() # re-invoke timer function manually to check for idempotence stack.set_stack_properties() stack._timer.cancel() self.assertEqual(len(stack.outputs), 1) self.assertEqual(len(stack.parameters), 1) self.assertEqual(len(stack.tags), 1)
def test_idempotent_properties(self, mock_template, _): region = make_test_region_obj("us-west-2") region.client = mock_client_method m_template = make_test_template() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() no_outp = len(stack.outputs) no_params = len(stack.parameters) no_tags = len(stack.tags) # re-invoke timer function manually to check for idempotence stack.set_stack_properties() stack._timer.cancel() self.assertEqual(len(stack.outputs), no_outp) self.assertEqual(len(stack.parameters), no_params) self.assertEqual(len(stack.tags), no_tags)
def test_import_existing(self, mock_template, _): region = make_test_region_obj("us-west-2") m_template = make_test_template() stack = Stack.import_existing( { "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/" "SampleStack/e722ae60-fe62-11e8-9a0e-0ae8cc519968" }, m_template, region, "test_test", mock.Mock(), ) stack._timer.cancel() self.assertEqual(stack.name, "SampleStack")
def test_resources(self, mock_template, m_res, _): region = make_test_region_obj("us-west-2") m_template = make_test_template() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() stack._resources = Resources([Resource("test_stack_id", resource_template)]) stack.resources() m_res.assert_called_once() stack._last_resource_refresh = datetime.now() stack.resources() m_res.assert_called_once() m_res.reset_mock() stack.resources(refresh=True) m_res.assert_called_once()
def test_import_existing(self, _): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.import_existing( { "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/" "SampleStack/e722ae60-fe62-11e8-9a0e-0ae8cc519968" }, m_template, region, "test_test", mock.Mock(), ) stack._timer.cancel() self.assertEqual(stack.name, "SampleStack")
def test_events(self, mock_template, m_eve, _): region = make_test_region_obj("us-west-2") m_template = make_test_template() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() generic_evnt = event_template.copy() not_generic_evnt = event_template.copy() generic_evnt["ResourceStatusReason"] = "Resource creation cancelled" generic_evnt["LogicalResourceId"] = "generic" not_generic_evnt["LogicalResourceId"] = "not-generic" stack._events = Events([Event(generic_evnt), Event(not_generic_evnt)]) actual = stack.events() m_eve.assert_called_once() self.assertEqual(len(actual), 2) stack._last_event_refresh = datetime.now() actual = stack.events(include_generic=False) m_eve.assert_called_once() self.assertEqual(len(actual), 1)
def test_resources(self, m_res, _): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() stack._resources = Resources( [Resource("test_stack_id", resource_template)]) stack.resources() m_res.assert_called_once() stack._last_resource_refresh = datetime.now() stack.resources() m_res.assert_called_once() m_res.reset_mock() stack.resources(refresh=True) m_res.assert_called_once()
def test_events(self, m_eve, _): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() generic_evnt = event_template.copy() not_generic_evnt = event_template.copy() generic_evnt["ResourceStatusReason"] = "Resource creation cancelled" generic_evnt["LogicalResourceId"] = "generic" not_generic_evnt["LogicalResourceId"] = "not-generic" stack._events = Events([Event(generic_evnt), Event(not_generic_evnt)]) actual = stack.events() m_eve.assert_called_once() self.assertEqual(len(actual), 2) stack._last_event_refresh = datetime.now() actual = stack.events(include_generic=False) m_eve.assert_called_once() self.assertEqual(len(actual), 1)
def test_refresh(self, m_kids, m_res, m_eve, m_prop, _): m_cf = mock.Mock() region = AWSRegionObject("us-west-2", m_cf) region.s3bucket = mock.Mock() region.client = mock_client_method m_template = mock.Mock() stack = Stack.create(region, "stack_name", m_template) stack._timer.cancel() m_prop.reset_mock() stack.refresh() m_prop.assert_called_once() m_res.assert_not_called() m_eve.assert_not_called() m_kids.assert_not_called() m_prop.reset_mock() stack.refresh(properties=False, events=True) m_eve.assert_called_once() m_res.assert_not_called() m_prop.assert_not_called() m_kids.assert_not_called() m_eve.reset_mock() stack.refresh(properties=False, resources=True) m_res.assert_called_once() m_eve.assert_not_called() m_prop.assert_not_called() m_kids.assert_not_called() m_res.reset_mock() stack.refresh(properties=False, children=True) m_kids.assert_called_once() m_res.assert_not_called() m_prop.assert_not_called() m_res.assert_not_called()
def _resources(stack: Stack, criteria): return {stack.id: stack.resources().filter(criteria)}
def _describe_stack_events(stack: Stack, criteria): return {stack.id: stack.events().filter(criteria)}
def _delete_stack(stack: Stack): stack.delete(stack_id=stack.id, client=stack.client) stack.refresh()
def _delete_stack(stack: Stack): stack.delete()
def _delete_stack(boto3_cache, job, aws_profile): client = boto3_cache.client("cloudformation", profile=aws_profile, region=job["region"]) Stack.delete(client=client, stack_id=job["stack_id"])