Exemple #1
0
async def test_deploy_release_many_apps(patch, magic, async_mock):
    patch.object(Apps, 'make_logger_for_app')
    patch.object(Database, 'update_release_state', new=async_mock())
    patch.init(TooManyActiveApps)
    patch.object(TooManyActiveApps, '__str__', return_value='too_many')

    stories = {'services': {}}
    Apps.apps = {}

    try:
        for i in range(20):
            Apps.apps[f'app_{i}'] = magic()
            Apps.apps[f'app_{i}'].owner_uuid = 'owner_uuid'
            stories['services'][f'service_{i}'] = {}

        await Apps.deploy_release(config={}, release=Release(
            app_uuid='app_id',
            app_name='app_name',
            version='app_version',
            environment={},
            stories=stories,
            maintenance=False,
            always_pull_images=False,
            app_dns='app_dns',
            state='QUEUED',
            deleted=False,
            owner_uuid='owner_uuid',
            owner_email='*****@*****.**',
            app_environment=AppEnvironment.PRODUCTION
        ))

        TooManyActiveApps.__init__.assert_called_with(20, 5)
        Database.update_release_state.mock.assert_called()
    finally:
        Apps.apps = {}  # Cleanup.
Exemple #2
0
async def test_reload_app_no_story(patch, config, logger, db, async_mock):
    app_id = 'app_id'
    app_name = 'app_name'

    patch.object(Apps, 'destroy_app', new=async_mock())
    patch.object(Apps, 'deploy_release', new=async_mock())

    release = Release(
        app_uuid=app_id,
        app_name=app_name,
        version=1,
        environment={},
        stories=None,
        maintenance=False,
        always_pull_images=False,
        app_dns='app_dns',
        state='QUEUED',
        deleted=True,
        owner_uuid='owner_uuid',
        owner_email='owner_email',
        app_environment=AppEnvironment.PRODUCTION
    )
    patch.object(Database, 'get_release_for_deployment',
                 new=async_mock(return_value=release))

    await Apps.reload_app(config, logger, app_id)

    Apps.deploy_release.mock.assert_not_called()
Exemple #3
0
async def test_get_release_for_deployment(patch, config, pool, async_mock,
                                          app_environment):
    app_id = 'my_app_id'
    expected_query = """
        with latest as (select app_uuid, max(id) as id
                        from releases
                        where state != 'NO_DEPLOY'::release_state
                        group by app_uuid)
        select app_uuid, id as version, config environment,
               payload stories, apps.name as app_name,
               maintenance, always_pull_images,
               hostname app_dns, state, deleted,
               apps.owner_uuid, owner_emails.email as owner_email,
               environment app_environment
        from latest
               inner join releases using (app_uuid, id)
               inner join apps on (latest.app_uuid = apps.uuid)
               inner join app_dns using (app_uuid)
               left join app_public.owner_emails on
                (apps.owner_uuid = owner_emails.owner_uuid)
        where app_uuid = $1;
        """

    patch.object(pool.con,
                 'fetchrow',
                 new=async_mock(
                     return_value={
                         'app_uuid': 'my_app_uuid',
                         'app_name': 'my_app_name',
                         'version': 'my_version',
                         'environment': 'my_environment',
                         'app_environment': app_environment,
                         'stories': 'my_stories',
                         'maintenance': 'my_maintenance',
                         'always_pull_images': 'my_always_pull_images',
                         'app_dns': 'my_app_dns',
                         'state': 'my_state',
                         'deleted': 'my_deleted',
                         'owner_uuid': 'my_owner_uuid',
                         'owner_email': 'my_owner_email'
                     }))
    ret = await Database.get_release_for_deployment(config, app_id)

    assert Database.get_pooled_conn.call_count == 1
    assert ret == Release(app_uuid='my_app_uuid',
                          app_name='my_app_name',
                          version='my_version',
                          environment='my_environment',
                          stories='my_stories',
                          maintenance='my_maintenance',
                          always_pull_images='my_always_pull_images',
                          app_dns='my_app_dns',
                          state='my_state',
                          deleted='my_deleted',
                          owner_uuid='my_owner_uuid',
                          owner_email='my_owner_email',
                          app_environment=AppEnvironment[app_environment])

    pool.con.fetchrow.mock.assert_called_with(expected_query, app_id)
Exemple #4
0
def test_app_init(magic, config, logger, env, always_pull_images):
    services = magic()
    stories = magic()
    expected_secrets = {}
    if env:
        for k, v in env.items():
            if not isinstance(v, dict):
                expected_secrets[k.lower()] = v

    version = 100
    app_config = magic()
    config.APP_DOMAIN = 'asyncyapp.com'

    app = App(app_data=AppData(release=Release(
        app_uuid='app_id',
        app_name='app_name',
        app_dns='app_dns',
        version=version,
        stories=stories,
        always_pull_images=always_pull_images,
        environment=env,
        owner_uuid='owner_1',
        owner_email='*****@*****.**',
        maintenance=False,
        deleted=False,
        state='QUEUED',
        app_environment=AppEnvironment.PRODUCTION),
                               app_config=app_config,
                               services=services,
                               config=config,
                               logger=logger))

    if env is None:
        env = {}

    assert app.app_id == 'app_id'
    assert app.app_dns == 'app_dns'
    assert app.config == config
    assert app.logger == logger
    assert app.owner_uuid == 'owner_1'
    assert app.owner_email == '*****@*****.**'
    assert app.stories == stories['stories']
    assert app.services == services
    assert app.always_pull_images == always_pull_images
    assert app.environment == env
    assert app.app_context['hostname'] == f'{app.app_dns}.asyncyapp.com'
    assert app.app_context['version'] == version
    assert app.app_context['secrets'] == expected_secrets
    assert app.entrypoint == stories['entrypoint']
    assert app.app_config == app_config

    if always_pull_images is True:
        assert app.image_pull_policy() == 'Always'
    else:
        assert app.image_pull_policy() == 'IfNotPresent'
Exemple #5
0
def app(config, logger, magic):
    return App(app_data=AppData(release=Release(
        app_uuid='app_uuid',
        app_name='app_name',
        app_dns='app_dns',
        owner_uuid='owner_uuid',
        owner_email='*****@*****.**',
        environment={},
        stories=magic(),
        version=magic(),
        always_pull_images=False,
        maintenance=False,
        deleted=False,
        state='QUEUED',
        app_environment=AppEnvironment.PRODUCTION),
                                config=config,
                                logger=logger,
                                services={},
                                app_config=magic()))
Exemple #6
0
async def test_deploy_release_many_volumes(patch, async_mock):
    patch.object(Apps, 'make_logger_for_app')
    patch.object(Database, 'update_release_state', new=async_mock())
    patch.init(TooManyVolumes)
    patch.object(TooManyVolumes, '__str__', return_value='too_many_vols')

    stories = {'services': {}}

    for i in range(10):
        stories['services'][f'service_{i}'] = {
            ServiceConstants.config: {
                'volumes': {
                    'a': {},
                    'b': {}
                }
            }
        }

    patch.object(Apps, 'get_services',
                 new=async_mock(return_value=stories['services']))
    await Apps.deploy_release(
        config={},
        release=Release(
            app_uuid='app_id',
            app_name='app_name',
            version='app_version',
            environment={},
            stories=stories,
            maintenance=False,
            always_pull_images=False,
            app_dns='app_dns',
            state='QUEUED',
            deleted=False,
            owner_uuid='owner_uuid',
            owner_email='owner_email',
            app_environment=AppEnvironment.PRODUCTION
        )
    )

    TooManyVolumes.__init__.assert_called_with(20, 15)
    Database.update_release_state.mock.assert_called()
Exemple #7
0
async def test_deploy_release(config, magic, patch, deleted,
                              async_mock, raise_exc, maintenance,
                              always_pull_images):
    patch.object(Reporter, 'capture_evt')
    patch.object(ReportingEvent, 'from_release')
    patch.object(Kubernetes, 'clean_namespace', new=async_mock())
    patch.object(Containers, 'init', new=async_mock())
    patch.object(Database, 'update_release_state', new=async_mock())
    app_logger = magic()
    patch.object(Apps, 'make_logger_for_app', return_value=app_logger)
    Apps.apps = {}
    services = magic()

    app_config = magic()
    patch.object(Apps, 'get_app_config', return_value=app_config)

    patch.object(Apps, 'get_services', new=async_mock(return_value=services))
    patch.init(App)
    if raise_exc is not None:
        patch.object(App, 'bootstrap', new=async_mock(side_effect=raise_exc()))
    else:
        patch.object(App, 'bootstrap', new=async_mock())

    release = Release(
        app_uuid='app_id',
        app_name='app_name',
        version='version',
        environment={'env': True},
        stories={'stories': True},
        maintenance=maintenance,
        always_pull_images=always_pull_images,
        app_dns='app_dns',
        state='QUEUED',
        deleted=deleted,
        owner_uuid='owner_uuid',
        owner_email='owner_email',
        app_environment=AppEnvironment.PRODUCTION
    )

    await Apps.deploy_release(config=config, release=release)

    if maintenance:
        assert Database.update_release_state.mock.call_count == 0
        app_logger.warn.assert_called()
    elif deleted:
        app_logger.warn.assert_called()
        Database.update_release_state.mock.assert_called_with(
            app_logger, config, 'app_id', 'version', ReleaseState.NO_DEPLOY)
    else:
        assert Database.update_release_state.mock.mock_calls[0] == mock.call(
            app_logger, config, 'app_id', 'version', ReleaseState.DEPLOYING)

        App.__init__.assert_called_with(app_data=AppData(
            release=release,
            config=config,
            logger=app_logger,
            services=services,
            app_config=app_config
        ))

        App.bootstrap.mock.assert_called()
        Containers.init.mock.assert_called()
        assert Apps.apps.get('app_id') is not (raise_exc is None)
        if raise_exc == exc:
            # ReportingEvent.from_release.assert_called_with(
            #     app.release, 'App Destroy Failed', exc_info=err)

            Reporter.capture_evt.assert_called_with(
                ReportingEvent.from_release.return_value)
            assert \
                Database.update_release_state.mock.mock_calls[1] \
                == mock.call(app_logger, config, 'app_id', 'version',
                             ReleaseState.TEMP_DEPLOYMENT_FAILURE)
        elif raise_exc == asyncy_exc:
            assert \
                Database.update_release_state.mock.mock_calls[1] \
                == mock.call(app_logger, config, 'app_id',
                             'version', ReleaseState.FAILED)
        else:
            assert \
                Database.update_release_state.mock.mock_calls[1] \
                == mock.call(app_logger, config,
                             'app_id', 'version', ReleaseState.DEPLOYED)
Exemple #8
0
async def test_reload_app(patch, config, logger, db, async_mock,
                          magic, raise_exc, previous_state,
                          app_environment_db, app_environment_config):
    config.APP_ENVIRONMENT = AppEnvironment[app_environment_config]
    old_app = magic()
    app_id = 'app_id'
    app_name = 'app_name'
    app_dns = 'app_dns'
    Apps.apps = {app_id: old_app}
    patch.object(Reporter, 'capture_evt')
    patch.object(ReportingEvent, 'from_release')
    app_logger = magic()
    patch.object(Apps, 'make_logger_for_app', return_value=app_logger)
    patch.object(Database, 'update_release_state', new=async_mock())

    patch.object(Apps, 'destroy_app', new=async_mock())
    if raise_exc:
        patch.object(Apps, 'deploy_release',
                     new=async_mock(side_effect=raise_exc()))
    else:
        patch.object(Apps, 'deploy_release', new=async_mock())

    release = Release(
        app_uuid=app_id,
        app_name=app_name,
        version=1,
        environment={},
        stories={},
        maintenance=False,
        always_pull_images=False,
        app_dns=app_dns,
        state=previous_state,
        deleted=True,
        owner_uuid='owner_uuid',
        owner_email='*****@*****.**',
        app_environment=AppEnvironment[app_environment_db]
    )

    patch.object(Database, 'get_release_for_deployment',
                 new=async_mock(return_value=release))

    await Apps.reload_app(config, logger, app_id)

    Apps.destroy_app.mock.assert_called_with(old_app, silent=True,
                                             update_db_state=True)

    if AppEnvironment[app_environment_db] != \
            AppEnvironment[app_environment_config]:
        Apps.deploy_release.mock.assert_not_called()
        logger.info.assert_called()
        logger.error.assert_not_called()
        logger.warn.assert_not_called()
        Database.update_release_state.mock.assert_not_called()
        return

    if previous_state == 'FAILED':
        Apps.deploy_release.mock.assert_not_called()
        logger.warn.assert_called()
        logger.error.assert_not_called()
        Database.update_release_state.mock.assert_not_called()
        return

    Apps.deploy_release.mock.assert_called_with(
        config=config, release=release
    )

    if raise_exc:
        logger.error.assert_called()
        assert ReportingEvent.from_release.mock_calls[0][1][0] == release
        assert ReportingEvent.from_release.mock_calls[0][1][
            1] == Events.APP_RELOAD_FAILED
        assert isinstance(
            ReportingEvent.from_release.mock_calls[0][2]['exc_info'],
            BaseException)

        Reporter.capture_evt.assert_called_with(
            ReportingEvent.from_release.return_value)
    else:
        logger.error.assert_not_called()

    if raise_exc == asyncio_timeout_exc:
        Database.update_release_state.mock.assert_called_with(
            app_logger, config, 'app_id', 1, ReleaseState.TIMED_OUT)