def test_get_ecs_service_events(self): # Given since = datetime.datetime(2017, 3, 8, 12, 15, 0, 0, tzinfo=tzlocal()) ecs_service_events_1 = [ { u'createdAt': datetime.datetime(2017, 3, 8, 12, 15, 9, 13000, tzinfo=tzlocal()), u'id': u'efbfce1c-c7d0-43be-a9a8-d18ad70e9d8b', u'message': u'(service aslive-grahamlyons-test) has started 2' }, # the event blow should *not* be returned (it's before since) { u'createdAt': datetime.datetime(2017, 3, 8, 12, 14, 30, 0, tzinfo=tzlocal()), u'id': u'efbfce1c-c7d0-43be-a9a8-d18ad70e9d8b', u'message': u'old event' } ] ecs_service_events_2 = [{ u'createdAt': datetime.datetime(2017, 3, 8, 12, 15, 46, 32000, tzinfo=tzlocal()), u'id': u'03c1bf6b-4054-4828-adc0-edce84d96c99', u'message': u'(service aslive-grahamlyons-test) has reached a' }, { u'createdAt': datetime.datetime(2017, 3, 8, 12, 15, 21, 649000, tzinfo=tzlocal()), u'id': u'66364f80-7713-4260-a8d7-39ec8207f4a9', u'message': u'(service aslive-grahamlyons-test) registered 2 ' }] ecs_event_iterator = ECSEventIterator(ANY, ANY, ANY, ANY, ANY) # When events_1 = ecs_event_iterator._get_new_ecs_service_events( {'services': [{ 'events': ecs_service_events_1[:1] }]}, since) events_2 = ecs_event_iterator._get_new_ecs_service_events( { 'services': [{ 'events': ecs_service_events_1[:1] + ecs_service_events_2 }] }, since) # Then assert events_1 == ecs_service_events_1[:1] assert events_2 == list(reversed(ecs_service_events_2)) assert events_1 + events_2 == \ ecs_service_events_1[:1] + list(reversed(ecs_service_events_2))
def test_deployment_completed_for_new_service(self): environment = 'dummy-environment' component = 'dummy-component' version = 'dummy-version' cluster = 'dummy-cluster' boto_session = MagicMock(spec=Session) mock_ecs_client = Mock() task_definition_arn = ('arn:aws:ecs:eu-west-3:111111111111:' 'task-definition/{}:1'.format(component)), def describe_services_generator(running_counts): for running_count in running_counts: pending_count = 0 yield { 'services': [{ 'clusterArn': 'arn:aws:ecs:eu-1:7:cstr/non-prod', 'deployments': [{ 'desiredCount': 2, 'createdAt': datetime.datetime(2017, 3, 8, 12, 15, 9, 13000), 'id': 'ecs-svc/9223370553143707624', 'runningCount': running_count, 'pendingCount': pending_count, 'status': 'PRIMARY', 'taskDefinition': task_definition_arn, }], 'loadBalancers': [{ 'containerName': 'app', 'containerPort': 8000, 'targetGroupArn': 'd035fe071cf0069f' }], 'status': 'ACTIVE', 'taskDefinition': task_definition_arn }] } mock_ecs_client.describe_services.side_effect = \ describe_services_generator([0, 0, 1, 2, 2, 2, 2, 2]) mock_ecs_client.describe_task_definition.return_value = { 'taskDefinition': { 'containerDefinitions': [{ 'cpu': 64, 'dockerLabels': { 'component': component, 'env': 'ci', 'team': 'platform', 'version': '123' }, 'environment': [ { 'name': 'VERSION', 'value': version }, { 'name': 'COMPONENT', 'value': component }, ], 'essential': True, 'image': ('111111111111.dkr.ecr.eu-west-1.amazonaws.com/' '{}:{}'.format(component, version)), 'volumesFrom': [] }], 'status': 'ACTIVE', 'taskDefinitionArn': task_definition_arn, 'taskRoleArn': 'arn:aws:iam::7:role/role', 'volumes': [] } } boto_session.client.return_value = mock_ecs_client events = ECSEventIterator(cluster, environment, component, version, boto_session) event_list = [e for e in events] assert len(event_list) == 8 assert not event_list[0].done assert event_list[0].running == 0 assert event_list[0].desired == 2 assert event_list[7].done assert event_list[7].running == 2 assert event_list[7].desired == 2
def test_memoization_on_object_instance(self): environment = 'dummy-environment' component = 'dummy-component' version = 'dummy-version' cluster = 'dummy-cluster' boto_session = MagicMock(spec=Session) mock_ecs_client = Mock() task_definition_arn = ('arn:aws:ecs:eu-west-3:111111111111:' 'task-definition/{}:1'.format(component)), mock_ecs_client.describe_services.return_value = { 'services': [{ 'clusterArn': 'arn:aws:ecs:eu-1:7:cstr/non-prod', 'deployments': [{ 'desiredCount': 2, u'createdAt': datetime.datetime(2017, 3, 8, 12, 15, 9, 13000, tzinfo=tzlocal()), 'id': 'ecs-svc/9223370553143707624', 'runningCount': 1, 'pendingCount': 1, 'status': 'PRIMARY', 'taskDefinition': task_definition_arn, }], 'status': 'ACTIVE', 'taskDefinition': task_definition_arn }] } mock_ecs_client.describe_task_definition.return_value = { 'taskDefinition': { 'containerDefinitions': [{ 'cpu': 64, 'dockerLabels': { 'component': component, 'env': 'ci', 'team': 'platform', 'version': '123' }, 'image': ('111111111111.dkr.ecr.eu-west-1.amazonaws.com/' '{}:{}'.format(component, version)), }], 'status': 'ACTIVE', 'taskDefinitionArn': task_definition_arn, 'taskRoleArn': 'arn:aws:iam::7:role/role', 'volumes': [] } } boto_session.client.return_value = mock_ecs_client events = ECSEventIterator(cluster, environment, component, version, boto_session) [e.done for e in islice(events, 1000)] boto_session.client.assert_called_once() mock_ecs_client.describe_task_definition.assert_called_once()
def test_monitor_image_does_not_match(self, deployment_data): environment = deployment_data['environment'] component = deployment_data['component'] version = deployment_data['version'] cluster = 'ecs-cluster' boto_session = MagicMock(spec=Session) mock_ecs_client = Mock() task_definition_arn = ('arn:aws:ecs:eu-west-3:111111111111:' 'task-definition/{}:1'.format(component)), mock_ecs_client.describe_services.return_value = { 'services': [{ 'clusterArn': 'arn:aws:ecs:eu-1:7:cluster/non-production', 'deployments': [{ 'desiredCount': 2, 'id': 'ecs-svc/9223370553143707624', 'pendingCount': 0, 'runningCount': 2, 'status': 'PRIMARY', 'taskDefinition': task_definition_arn, 'updatedAt': datetime.datetime(2017, 1, 6, 13, 57), 'createdAt': datetime.datetime(2017, 1, 6, 13, 57) }], 'status': 'ACTIVE', 'taskDefinition': task_definition_arn }] } mock_ecs_client.describe_task_definition.return_value = { 'taskDefinition': { 'containerDefinitions': [{ 'dockerLabels': { 'component': component, 'env': 'ci', 'team': 'platform', 'version': '123' }, 'environment': [ { 'name': 'VERSION', 'value': version }, { 'name': 'COMPONENT', 'value': component }, ], 'image': 'ecr/none', }], 'taskDefinitionArn': task_definition_arn, } } boto_session.client.return_value = mock_ecs_client events = ECSEventIterator(cluster, environment, component, version, boto_session) self.assertRaises(ImageDoesNotMatchError, lambda: [e for e in events]) try: next(iter(events)) except ImageDoesNotMatchError as e: assert 'none' in str(e) assert '{}:{}'.format(component, version) in str(e)
def test_monitor_exited_when_the_deployment_is_stable( self, deployment_data): environment = deployment_data['environment'] component = deployment_data['component'] version = deployment_data['version'] cluster = deployment_data['cluster'] boto_session = MagicMock(spec=Session) mock_ecs_client = Mock() task_definition_arn = ('arn:aws:ecs:eu-west-3:111111111111:' 'task-definition/{}:1'.format(component)), mock_ecs_client.describe_services.return_value = { 'failures': [], 'services': [{ 'clusterArn': 'arn:aws:ecs:eu-1:7:cluster/non-production', 'createdAt': datetime.datetime(2017, 1, 6, 10, 58, 9), 'deployments': [ { 'createdAt': datetime.datetime(2017, 1, 6, 13, 57), 'desiredCount': 2, 'id': 'ecs-svc/9223370553143707624', 'pendingCount': 0, 'runningCount': 2, 'status': 'PRIMARY', 'taskDefinition': task_definition_arn, 'updatedAt': datetime.datetime(2017, 1, 6, 13, 57) }, ], 'desiredCount': 2, 'events': [{ 'createdAt': datetime.datetime(2017, 3, 10, 10, 27, 40, 1), 'id': '71e1ea54-61bd-4d5f-b6ae-ba0ba4a3c270', 'message': 'has reached a steady state.' }, { 'createdAt': datetime.datetime(2017, 3, 9, 16, 26, 49, 794), 'id': '851fd578-579d-4a23-8764-107f0cf1120c', 'message': 'registered 1 targets' }, { 'createdAt': datetime.datetime(2017, 3, 9, 16, 26, 37, 48000), 'id': '39e46d75-018e-4db4-a62d-1d76b4564132', 'message': 'has started 1 tasks' }], 'loadBalancers': [{ 'containerName': 'app', 'containerPort': 8000, 'targetGroupArn': 'd035fe071cf0069f' }], 'pendingCount': 0, 'roleArn': '20170106105800480922659dsq', 'runningCount': 2, 'serviceArn': 'aslive-testtf2469', 'serviceName': 'aslive-testtf2469', 'status': 'ACTIVE', 'taskDefinition': task_definition_arn }] } mock_ecs_client.describe_task_definition.return_value = { 'taskDefinition': { 'containerDefinitions': [{ 'cpu': 64, 'dockerLabels': { 'component': component, 'env': 'ci', 'team': 'platform', 'version': '123' }, 'environment': [ { 'name': 'VERSION', 'value': version }, { 'name': 'COMPONENT', 'value': component }, ], 'essential': True, 'image': ('111111111111.dkr.ecr.eu-west-1.amazonaws.com/' '{}:{}'.format(component, version)), 'volumesFrom': [] }], 'status': 'ACTIVE', 'taskDefinitionArn': task_definition_arn, 'taskRoleArn': 'arn:aws:iam::7:role/role', 'volumes': [] } } boto_session.client.return_value = mock_ecs_client events = ECSEventIterator(cluster, environment, component, version, boto_session) event_list = [e for e in events] # Then assert len(event_list) == 5 assert event_list[0].messages == [ 'has started 1 tasks', 'registered 1 targets', 'has reached a steady state.' ] assert event_list[4].done assert event_list[4].previous_running == 0