async def test_autoscale_insufficient_data(mocker, app_factory, conn): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', X_AUTOSCALING='on', X_AUTOSCALING_MIN=1), ] mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: with async_patch('autoscaler.app.scale') as mock_scale: await autoscale(conn) assert not mock_scale.called
async def test_profile_credential(hass): """Test credentials with profile name.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component(hass, 'aws', { 'aws': { 'credentials': { 'name': 'test', 'profile_name': 'test-profile', }, 'notify': [{ 'service': 'sns', 'credential_name': 'test', 'name': 'SNS Test', 'region_name': 'us-east-1', }] } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('test'), MockAioSession) assert hass.services.has_service('notify', 'sns_test') is True await hass.services.async_call( 'notify', 'sns_test', {'title': 'test', 'message': 'test', 'target': 'ARN'}, blocking=True )
async def test_autoscale_scale_up_indicates_it_is_at_max( mocker, app_factory, conn, create_metric): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', instances=9, X_AUTOSCALING='on', X_AUTOSCALING_MAX=10), ] # pass is_new_app test - this ensures that we don't attempt to autoscale transitory apps created # as part of blue/green depoloyment process. await create_metric(dt.datetime.now() - dt.timedelta(minutes=31), 'test_app', 'test_space', 2, 95) for i in range(35): await create_metric(dt.datetime.now() - dt.timedelta(seconds=30), 'test_app', 'test_space', 2, 95) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: await autoscale(conn) assert mock_notify.called assert mock_notify.call_args[0] == ( 'test_app', 'scaled up to 10 - avg cpu 95.00 [max]')
async def test_notify_credential(hass): """Test notify service can use access key directly.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component( hass, 'aws', { 'aws': { 'notify': [{ 'service': 'sqs', 'credential_name': 'test', 'name': 'SQS Test', 'region_name': 'us-east-1', 'aws_access_key_id': 'some-key', 'aws_secret_access_key': 'some-secret', }] } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('default'), MockAioSession) assert hass.services.has_service('notify', 'sqs_test') is True await hass.services.async_call('notify', 'sqs_test', { 'message': 'test', 'target': 'ARN' }, blocking=True)
async def test_empty_credential(hass): """Test a default config will be create for empty credential section.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component(hass, 'aws', { 'aws': { 'notify': [{ 'service': 'lambda', 'name': 'New Lambda Test', 'region_name': 'us-east-1', }] } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('default'), MockAioSession) assert hass.services.has_service('notify', 'new_lambda_test') is True await hass.services.async_call( 'notify', 'new_lambda_test', {'message': 'test', 'target': 'ARN'}, blocking=True )
async def test_empty_credential(hass): """Test a default config will be create for empty credential section.""" with async_patch("aiobotocore.AioSession", new=MockAioSession): await async_setup_component( hass, "aws", { "aws": { "notify": [{ "service": "lambda", "name": "New Lambda Test", "region_name": "us-east-1", }] } }, ) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 session = sessions.get("default") assert isinstance(session, MockAioSession) assert hass.services.has_service("notify", "new_lambda_test") is True await hass.services.async_call("notify", "new_lambda_test", { "message": "test", "target": "ARN" }, blocking=True) session.invoke.assert_awaited_once()
async def test_notify_credential(hass): """Test notify service can use access key directly.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component(hass, 'aws', { 'aws': { 'notify': [{ 'service': 'sqs', 'credential_name': 'test', 'name': 'SQS Test', 'region_name': 'us-east-1', 'aws_access_key_id': 'some-key', 'aws_secret_access_key': 'some-secret', }] } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('default'), MockAioSession) assert hass.services.has_service('notify', 'sqs_test') is True await hass.services.async_call( 'notify', 'sqs_test', {'message': 'test', 'target': 'ARN'}, blocking=True )
async def test_credential_skip_validate(hass): """Test credential can skip validate.""" with async_patch("aiobotocore.AioSession", new=MockAioSession): await async_setup_component( hass, "aws", { "aws": { "credentials": [{ "name": "key", "aws_access_key_id": "not-valid", "aws_secret_access_key": "dont-care", "validate": False, }] } }, ) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 session = sessions.get("key") assert isinstance(session, MockAioSession) session.get_user.assert_not_awaited()
async def test_autoscale_scale_down(mocker, app_factory, conn, create_metric): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', instances=5, X_AUTOSCALING='on', X_AUTOSCALING_MIN=2), ] await create_metric(dt.datetime.now() - dt.timedelta(minutes=30), 'test_app', 'test_space', 5, 5) for i in range(10): await create_metric(dt.datetime.now() - dt.timedelta(seconds=30), 'test_app', 'test_space', 5, 5) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: await autoscale(conn) async with conn.cursor() as cur: await cur.execute('SELECT app, space, instances FROM actions;') assert cur.rowcount == 1 assert await cur.fetchone() == ('test_app', 'test_space', 4) assert mock_notify.called assert mock_notify.call_args[0] == ('test_app', 'scaled down to 4 - avg cpu 5.00')
async def test_autoscale_scale_down_to_min_indicates_it_is_now_at_min( mocker, app_factory, conn, create_metric): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', instances=3, X_AUTOSCALING='on', X_AUTOSCALING_MIN=2), ] await create_metric(dt.datetime.now() - dt.timedelta(minutes=30), 'test_app', 'test_space', 5, 5) for i in range(10): await create_metric(dt.datetime.now() - dt.timedelta(seconds=30), 'test_app', 'test_space', 5, 5) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: await autoscale(conn) assert mock_notify.called assert mock_notify.call_args[0] == ( 'test_app', 'scaled down to 2 - avg cpu 5.00 [min]')
async def test_notify_credential_profile(hass): """Test notify service can use profile directly.""" with async_patch("aiobotocore.AioSession", new=MockAioSession): await async_setup_component( hass, "aws", { "aws": { "notify": [{ "service": "sqs", "name": "SQS Test", "region_name": "us-east-1", "profile_name": "test", }] } }, ) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get("default"), MockAioSession) assert hass.services.has_service("notify", "sqs_test") is True await hass.services.async_call("notify", "sqs_test", { "message": "test", "target": "ARN" }, blocking=True)
async def test_profile_credential(hass): """Test credentials with profile name.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component( hass, 'aws', { 'aws': { 'credentials': { 'name': 'test', 'profile_name': 'test-profile', }, 'notify': [{ 'service': 'sns', 'credential_name': 'test', 'name': 'SNS Test', 'region_name': 'us-east-1', }] } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('test'), MockAioSession) assert hass.services.has_service('notify', 'sns_test') is True await hass.services.async_call('notify', 'sns_test', { 'title': 'test', 'message': 'test', 'target': 'ARN' }, blocking=True)
async def test_empty_credential(hass): """Test a default config will be create for empty credential section.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component( hass, 'aws', { 'aws': { 'notify': [{ 'service': 'lambda', 'name': 'New Lambda Test', 'region_name': 'us-east-1', }] } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('default'), MockAioSession) assert hass.services.has_service('notify', 'new_lambda_test') is True await hass.services.async_call('notify', 'new_lambda_test', { 'message': 'test', 'target': 'ARN' }, blocking=True)
async def test_autoscale_scale_up(mocker, app_factory, conn, create_metric): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', instances=5, X_AUTOSCALING='on', X_AUTOSCALING_MAX=10), ] # pass is_new_app test - this ensures that we don't attempt to autoscale transitory apps created # as part of blue/green depoloyment process. await create_metric(dt.datetime.now() - dt.timedelta(minutes=31), 'test_app', 'test_space', 2, 95) for i in range(35): await create_metric(dt.datetime.now() - dt.timedelta(seconds=30), 'test_app', 'test_space', 2, 95) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: await autoscale(conn) async with conn.cursor() as cur: await cur.execute('SELECT app, space, instances FROM actions;') assert cur.rowcount == 1 assert await cur.fetchone() == ('test_app', 'test_space', 6) assert mock_notify.called assert mock_notify.call_args[0] == ('test_app', 'scaled up to 6 - avg cpu 95.00')
async def test_autoscale_scales_down_if_above_max(mocker, app_factory, create_metric, conn): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', instances=11, X_AUTOSCALING='on', X_AUTOSCALING_MAX=10), ] await create_metric(dt.datetime.now() - dt.timedelta(minutes=30), 'test_app', 'test_space', 5, 5) for i in range(10): await create_metric(dt.datetime.now() - dt.timedelta(seconds=30), 'test_app', 'test_space', 2, 95) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: await autoscale(conn) assert mock_notify.called assert mock_notify.call_args[0] == ( 'test_app', 'scaled down to 10 as instance count above maximum')
async def test_empty_config(hass): """Test a default config will be create for empty config.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component(hass, 'aws', {'aws': {}}) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('default'), MockAioSession)
async def test_empty_config(hass): """Test a default config will be create for empty config.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component(hass, 'aws', { 'aws': {} }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 assert isinstance(sessions.get('default'), MockAioSession)
async def test_autoscale_is_cooldown(mocker, app_factory, conn, create_action): apps = [ app_factory('test_app', 'test_space', X_AUTOSCALING='on'), ] await create_action(dt.datetime.now(), 'test_app', 'test_space', 1) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: await autoscale(conn) assert mock_notify.called_with('is in cool down period', is_verbose=True)
async def test_empty_config(hass): """Test a default config will be create for empty config.""" with async_patch("aiobotocore.AioSession", new=MockAioSession): await async_setup_component(hass, "aws", {"aws": {}}) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 session = sessions.get("default") assert isinstance(session, MockAioSession) # we don't validate auto-created default profile session.get_user.assert_not_awaited()
async def test_autoscale_at_max_scale(mocker, app_factory, conn, create_metric): await reset_database(conn) apps = [ app_factory('test_app', 'test_space', instances=10, X_AUTOSCALING='on', X_AUTOSCALING_MAX=10), ] for i in range(10): await create_metric(dt.datetime.now() - dt.timedelta(seconds=30), 'test_app', 'test_space', 2, 95) mock_get_client = mocker.patch('autoscaler.app.get_client') mock_get_client.return_value.apps.list.return_value = apps with async_patch('autoscaler.app.notify') as mock_notify: with async_patch('autoscaler.app.scale') as mock_scale: await autoscale(conn) assert not mock_notify.called assert not mock_scale.called
async def test_access_key_credential(hass): """Test credentials with access key.""" with async_patch("aiobotocore.AioSession", new=MockAioSession): await async_setup_component( hass, "aws", { "aws": { "credentials": [ { "name": "test", "profile_name": "test-profile" }, { "name": "key", "aws_access_key_id": "test-key", "aws_secret_access_key": "test-secret", }, ], "notify": [{ "service": "sns", "credential_name": "key", "name": "SNS Test", "region_name": "us-east-1", }], } }, ) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 2 session = sessions.get("key") assert isinstance(session, MockAioSession) assert hass.services.has_service("notify", "sns_test") is True await hass.services.async_call( "notify", "sns_test", { "title": "test", "message": "test", "target": "ARN" }, blocking=True, ) session.publish.assert_awaited_once()
async def test_credential_skip_validate(hass): """Test credential can skip validate.""" with async_patch('aiobotocore.AioSession', new=MockAioSession): await async_setup_component( hass, 'aws', { 'aws': { 'credentials': [ { 'name': 'key', 'aws_access_key_id': 'not-valid', 'aws_secret_access_key': 'dont-care', 'validate': False }, ], } }) await hass.async_block_till_done() sessions = hass.data[aws.DATA_SESSIONS] assert sessions is not None assert len(sessions) == 1 session = sessions.get('key') assert isinstance(session, MockAioSession) session.get_user.assert_not_awaited()