def create_deletion_deployer(client, ui): # type: (TypedAWSClient, UI) -> Deployer return Deployer( application_builder=ApplicationGraphBuilder(), deps_builder=DependencyBuilder(), build_stage=BuildStage(steps=[]), plan_stage=NoopPlanner(), sweeper=ResourceSweeper(), executor=Executor(client, ui), recorder=ResultsRecorder(osutils=OSUtils()), )
def create_default_deployer(session, config, ui): # type: (Session, Config, UI) -> Deployer client = TypedAWSClient(session) osutils = OSUtils() return Deployer( application_builder=ApplicationGraphBuilder(), deps_builder=DependencyBuilder(), build_stage=create_build_stage( osutils, UI(), TemplatedSwaggerGenerator(), ), plan_stage=PlanStage( osutils=osutils, remote_state=RemoteState( client, config.deployed_resources(config.chalice_stage)), ), sweeper=ResourceSweeper(), executor=Executor(client, ui), recorder=ResultsRecorder(osutils=osutils), )
def setup_method(self): super(TestUnreferencedResourcePlanner, self).setup_method() self.sweeper = ResourceSweeper()
class TestUnreferencedResourcePlanner(BasePlannerTests): def setup_method(self): super(TestUnreferencedResourcePlanner, self).setup_method() self.sweeper = ResourceSweeper() def execute(self, plan, config): self.sweeper.execute(models.Plan(plan, messages={}), config) @pytest.fixture def function_resource(self): return create_function_resource('myfunction') def one_deployed_lambda_function(self, name='myfunction', arn='arn'): return { 'resources': [{ 'name': name, 'resource_type': 'lambda_function', 'lambda_arn': arn, }] } def test_noop_when_all_resources_accounted_for(self, function_resource): plan = [ models.RecordResource( resource_type='lambda_function', resource_name='myfunction', name='foo', ) ] original_plan = plan[:] deployed = self.one_deployed_lambda_function(name='myfunction') config = FakeConfig(deployed) self.execute(plan, config) # We shouldn't add anything to the list. assert plan == original_plan def test_will_delete_unreferenced_resource(self): plan = [] deployed = self.one_deployed_lambda_function() config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 1 assert plan[0].method_name == 'delete_function' assert plan[0].params == {'function_name': 'arn'} def test_supports_multiple_unreferenced_and_unchanged(self): first = create_function_resource('first') second = create_function_resource('second') third = create_function_resource('third') plan = [ models.RecordResource( resource_type='lambda_function', resource_name=first.resource_name, name='foo', ), models.RecordResource( resource_type='asdf', resource_name=second.resource_name, name='foo', ) ] deployed = { 'resources': [{ 'name': second.resource_name, 'resource_type': 'lambda_function', 'lambda_arn': 'second_arn', }, { 'name': third.resource_name, 'resource_type': 'lambda_function', 'lambda_arn': 'third_arn', }] } config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 3 assert plan[2].method_name == 'delete_function' assert plan[2].params == {'function_name': 'third_arn'} def test_can_delete_iam_role(self): plan = [] deployed = { 'resources': [{ 'name': 'myrole', 'resource_type': 'iam_role', 'role_name': 'myrole', 'role_arn': 'arn:role/myrole', }] } config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 1 assert plan[0].method_name == 'delete_role' assert plan[0].params == {'name': 'myrole'} def test_correct_deletion_order_for_dependencies(self): plan = [] deployed = { # This is the order they were deployed. While not # strictly required for IAM Roles, we typically # want to delete resources in the reverse order they # were created. 'resources': [{ 'name': 'myrole', 'resource_type': 'iam_role', 'role_name': 'myrole', 'role_arn': 'arn:role/myrole', }, { 'name': 'myrole2', 'resource_type': 'iam_role', 'role_name': 'myrole2', 'role_arn': 'arn:role/myrole2', }, { 'name': 'myfunction', 'resource_type': 'lambda_function', 'lambda_arn': 'my:arn', }] } config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 3 expected_api_calls = [p.method_name for p in plan] assert expected_api_calls == [ 'delete_function', 'delete_role', 'delete_role' ] expected_api_args = [p.params for p in plan] assert expected_api_args == [ { 'function_name': 'my:arn' }, { 'name': 'myrole2' }, { 'name': 'myrole' }, ] def test_can_delete_scheduled_event(self): plan = [] deployed = { 'resources': [{ 'name': 'index-event', 'resource_type': 'cloudwatch_event', 'rule_name': 'app-dev-index-event', }] } config = FakeConfig(deployed) self.execute(plan, config) assert plan == [ models.APICall( method_name='delete_rule', params={'rule_name': 'app-dev-index-event'}, ) ] def test_can_delete_s3_event(self): plan = [] deployed = { 'resources': [{ 'name': 'test-s3-event', 'resource_type': 's3_event', 'bucket': 'mybucket', 'lambda_arn': 'lambda_arn', }] } config = FakeConfig(deployed) self.execute(plan, config) assert plan == [ models.APICall( method_name='disconnect_s3_bucket_from_lambda', params={ 'bucket': 'mybucket', 'function_arn': 'lambda_arn' }, ) ] def test_can_delete_rest_api(self): plan = [] deployed = { 'resources': [{ 'name': 'rest_api', 'rest_api_id': 'my_rest_api_id', 'resource_type': 'rest_api', }] } config = FakeConfig(deployed) self.execute(plan, config) assert plan == [ models.APICall( method_name='delete_rest_api', params={'rest_api_id': 'my_rest_api_id'}, ) ] def test_can_handle_when_resource_changes_values(self): plan = self.determine_plan( models.S3BucketNotification( resource_name='test-s3-event', bucket='NEWBUCKET', events=['s3:ObjectCreated:*'], prefix=None, suffix=None, lambda_function=create_function_resource('function_name'), )) deployed = { 'resources': [{ 'name': 'test-s3-event', 'resource_type': 's3_event', 'bucket': 'OLDBUCKET', 'lambda_arn': 'lambda_arn', }] } config = FakeConfig(deployed) self.execute(plan, config) assert plan[-1] == models.APICall( method_name='disconnect_s3_bucket_from_lambda', params={ 'bucket': 'OLDBUCKET', 'function_arn': 'lambda_arn' }, ) def test_no_sweeping_when_resource_value_unchanged(self): plan = self.determine_plan( models.S3BucketNotification( resource_name='test-s3-event', bucket='EXISTING-BUCKET', events=['s3:ObjectCreated:*'], prefix=None, suffix=None, lambda_function=create_function_resource('function_name'), )) deployed = { 'resources': [{ 'name': 'test-s3-event', 'resource_type': 's3_event', 'bucket': 'EXISTING-BUCKET', 'lambda_arn': 'lambda_arn', }] } config = FakeConfig(deployed) original_plan = plan[:] self.execute(plan, config) assert plan == original_plan
def setup_method(self): self.sweeper = ResourceSweeper()
class TestUnreferencedResourcePlanner(object): def setup_method(self): self.sweeper = ResourceSweeper() def execute(self, plan, config): self.sweeper.execute(models.Plan(plan, messages={}), config) @pytest.fixture def function_resource(self): return create_function_resource('myfunction') def one_deployed_lambda_function(self, name='myfunction', arn='arn'): return { 'resources': [{ 'name': name, 'resource_type': 'lambda_function', 'lambda_arn': arn, }] } def test_noop_when_all_resources_accounted_for(self, function_resource): plan = [ models.RecordResource( resource_type='lambda_function', resource_name='myfunction', name='foo', ) ] original_plan = plan[:] deployed = self.one_deployed_lambda_function(name='myfunction') config = FakeConfig(deployed) self.execute(plan, config) # We shouldn't add anything to the list. assert plan == original_plan def test_will_delete_unreferenced_resource(self): plan = [] deployed = self.one_deployed_lambda_function() config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 1 assert plan[0].method_name == 'delete_function' assert plan[0].params == {'function_name': 'arn'} def test_supports_multiple_unreferenced_and_unchanged(self): first = create_function_resource('first') second = create_function_resource('second') third = create_function_resource('third') plan = [ models.RecordResource( resource_type='lambda_function', resource_name=first.resource_name, name='foo', ), models.RecordResource( resource_type='asdf', resource_name=second.resource_name, name='foo', ) ] deployed = { 'resources': [{ 'name': second.resource_name, 'resource_type': 'lambda_function', 'lambda_arn': 'second_arn', }, { 'name': third.resource_name, 'resource_type': 'lambda_function', 'lambda_arn': 'third_arn', }] } config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 3 assert plan[2].method_name == 'delete_function' assert plan[2].params == {'function_name': 'third_arn'} def test_can_delete_iam_role(self): plan = [] deployed = { 'resources': [{ 'name': 'myrole', 'resource_type': 'iam_role', 'role_name': 'myrole', 'role_arn': 'arn:role/myrole', }] } config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 1 assert plan[0].method_name == 'delete_role' assert plan[0].params == {'name': 'myrole'} def test_correct_deletion_order_for_dependencies(self): plan = [] deployed = { # This is the order they were deployed. While not # strictly required for IAM Roles, we typically # want to delete resources in the reverse order they # were created. 'resources': [ { 'name': 'myrole', 'resource_type': 'iam_role', 'role_name': 'myrole', 'role_arn': 'arn:role/myrole', }, { 'name': 'myrole2', 'resource_type': 'iam_role', 'role_name': 'myrole2', 'role_arn': 'arn:role/myrole2', }, { 'name': 'myfunction', 'resource_type': 'lambda_function', 'lambda_arn': 'my:arn', } ] } config = FakeConfig(deployed) self.execute(plan, config) assert len(plan) == 3 expected_api_calls = [p.method_name for p in plan] assert expected_api_calls == ['delete_function', 'delete_role', 'delete_role'] expected_api_args = [p.params for p in plan] assert expected_api_args == [ {'function_name': 'my:arn'}, {'name': 'myrole2'}, {'name': 'myrole'}, ] def test_can_delete_scheduled_event(self): plan = [] deployed = { 'resources': [{ 'name': 'index-event', 'resource_type': 'cloudwatch_event', 'rule_name': 'app-dev-index-event', }] } config = FakeConfig(deployed) self.execute(plan, config) assert plan == [ models.APICall( method_name='delete_rule', params={'rule_name': 'app-dev-index-event'}, ) ] def test_can_delete_rest_api(self): plan = [] deployed = { 'resources': [{ 'name': 'rest_api', 'rest_api_id': 'my_rest_api_id', 'resource_type': 'rest_api', }] } config = FakeConfig(deployed) self.execute(plan, config) assert plan == [ models.APICall( method_name='delete_rest_api', params={'rest_api_id': 'my_rest_api_id'}, ) ]