示例#1
0
def start_server(options: argparse.Namespace) -> None:
    if options.config_file and not os.path.exists(options.config_file):
        LOGGER.warning("Config file %s doesn't exist", options.config_file)

    if options.config_dir and not os.path.isdir(options.config_dir):
        LOGGER.warning("Config directory %s doesn't exist", options.config_dir)

    ibl = InmantaBootloader()
    setup_signal_handlers(ibl.stop)

    ioloop = IOLoop.current()

    # handle startup exceptions
    def _handle_startup_done(fut: asyncio.Future) -> None:
        if fut.cancelled():
            safe_shutdown(ioloop, ibl.stop)
        else:
            exc = fut.exception()
            if exc is not None:
                LOGGER.exception("Server setup failed", exc_info=exc)
                traceback.print_exception(type(exc), exc, exc.__traceback__)
                safe_shutdown(ioloop, ibl.stop)
            else:
                LOGGER.info("Server startup complete")

    ensure_future(ibl.start()).add_done_callback(_handle_startup_done)

    ioloop.start()
    LOGGER.info("Server shutdown complete")
    if not ibl.started:
        exit(EXIT_START_FAILED)
示例#2
0
async def server(server_pre_start):
    """
    :param event_loop: explicitly include event_loop to make sure event loop started before and closed after this fixture.
    May not be required
    """
    # fix for fact that pytest_tornado never set IOLoop._instance, the IOLoop of the main thread
    # causes handler failure

    ibl = InmantaBootloader()

    try:
        await ibl.start()
    except SliceStartupException as e:
        port = config.Config.get("server", "bind-port")
        output = subprocess.check_output(["ss", "-antp"])
        output = output.decode("utf-8")
        logger.debug(f"Port: {port}")
        logger.debug(f"Port usage: \n {output}")
        raise e

    yield ibl.restserver

    try:
        await asyncio.wait_for(ibl.stop(), 15)
    except concurrent.futures.TimeoutError:
        logger.exception("Timeout during stop of the server in teardown")

    logger.info("Server clean up done")
async def server_with_frequent_cleanups(server_pre_start, server_config,
                                        async_finalizer):
    config.Config.set("server", "compiler-report-retention", "2")
    config.Config.set("server", "cleanup-compiler-reports_interval", "1")
    ibl = InmantaBootloader()
    await ibl.start()
    yield ibl.restserver
    await asyncio.wait_for(ibl.stop(), 15)
def test_end_to_end():
    with splice_extension_in("test_module_path"):
        ibl = InmantaBootloader()

        config.server_enabled_extensions.set("testplugin")

        ctx = ibl.load_slices()
        byname = {sl.name: sl for sl in ctx.get_slices()}
        assert "testplugin.testslice" in byname
示例#5
0
async def startable_server(server_config):
    """
    This fixture returns the bootloader of a server which is not yet started.
    """
    bootloader = InmantaBootloader()
    yield bootloader
    try:
        await asyncio.wait_for(bootloader.stop(), 15)
    except concurrent.futures.TimeoutError:
        logger.exception("Timeout during stop of the server in teardown")
def test_end_to_end_2():
    with splice_extension_in("bad_module_path"):
        config.server_enabled_extensions.set("badplugin")

        ibl = InmantaBootloader()
        all = ibl._load_extensions()
        print(all)
        assert "badplugin" in all

    config.server_enabled_extensions.set("")
    all = ibl._load_extensions()
    assert "badplugin" not in all
def test_phase_1(caplog):
    with splice_extension_in("test_module_path"):
        ibl = InmantaBootloader()

        config.server_enabled_extensions.set("testplugin,noext")

        all = ibl._load_extensions()

        assert "testplugin" in all
        assert all["testplugin"] == inmanta_ext.testplugin.extension.setup

        log_contains(caplog, "inmanta.server.bootloader", logging.WARNING,
                     "Could not load extension inmanta_ext.noext")
async def test_custom_feature_manager(tmp_path, inmanta_config, postgres_db,
                                      database_name, clean_reset,
                                      unused_tcp_port_factory,
                                      async_finalizer):
    with splice_extension_in("test_module_path"):
        state_dir = str(tmp_path)
        port = str(unused_tcp_port_factory())
        config.Config.set("database", "name", database_name)
        config.Config.set("database", "host", "localhost")
        config.Config.set("database", "port", str(postgres_db.port))
        config.Config.set("database", "username", postgres_db.user)
        config.Config.set("database", "password", postgres_db.password)
        config.Config.set("database", "connection_timeout", str(1))
        config.Config.set("config", "state-dir", state_dir)
        config.Config.set("config", "log-dir", os.path.join(state_dir, "logs"))
        config.Config.set("agent_rest_transport", "port", port)
        config.Config.set("compiler_rest_transport", "port", port)
        config.Config.set("client_rest_transport", "port", port)
        config.Config.set("cmdline_rest_transport", "port", port)
        config.Config.set("server", "bind-port", port)
        config.Config.set("server", "bind-address", "127.0.0.1")
        config.server_enabled_extensions.set("testfm")

        ibl = InmantaBootloader()
        async_finalizer.add(partial(ibl.stop, timeout=15))
        await ibl.start()
        server = ibl.restserver

        fm = server.get_slice(SLICE_SERVER).feature_manager

        assert not fm.enabled(None)
        assert not fm.enabled("a")
示例#9
0
def print_versions_installed_components_and_exit() -> None:
    bootloader = InmantaBootloader()
    app_context = bootloader.load_slices()
    product_metadata = app_context.get_product_metadata()
    extension_statuses = app_context.get_extension_statuses()
    if product_metadata.version:
        print(f"{product_metadata.product} ({product_metadata.edition}): {product_metadata.version}")
    else:
        print(f"{product_metadata.product} ({product_metadata.edition}): version unknown")
    print(f"Compiler version: {get_compiler_version()}")
    if extension_statuses:
        print("Extensions:")
        for ext_status in extension_statuses:
            print(f"    * {ext_status.name}: {ext_status.version}")
    else:
        print("Extensions: No extensions found")
    sys.exit(0)
def test_phase_2():
    with splice_extension_in("test_module_path"):
        import inmanta_ext.testplugin.extension

        ibl = InmantaBootloader()
        all = {"testplugin": inmanta_ext.testplugin.extension.setup}

        ctx = ibl._collect_slices(all)

        byname = {sl.name: sl for sl in ctx._slices}

        assert "testplugin.testslice" in byname

        # load slice in wrong namespace
        with pytest.raises(InvalidSliceNameException):
            all = {"test": inmanta_ext.testplugin.extension.setup}
            ctx = ibl._collect_slices(all)
def test_load_and_filter(caplog):
    caplog.set_level(logging.INFO)

    with splice_extension_in("test_module_path"):
        ibl = InmantaBootloader()

        plugin_pkgs = ibl._discover_plugin_packages()
        assert "inmanta_ext.core" in plugin_pkgs
        assert len(plugin_pkgs) == 1

        # When extensions are available but not enabled, log a message with the correct option
        log_contains(caplog, "inmanta.server.bootloader", logging.INFO,
                     "Load extensions by setting configuration option")

        with pytest.raises(PluginLoadFailed):
            config.server_enabled_extensions.set("unknown")
            plugin_pkgs = ibl._discover_plugin_packages()
async def test_startup_failure(async_finalizer, server_config):
    with splice_extension_in("bad_module_path"):
        config.server_enabled_extensions.set("badplugin")

        ibl = InmantaBootloader()
        async_finalizer.add(partial(ibl.stop, timeout=15))
        with pytest.raises(Exception) as e:
            await ibl.start()

        print(e.value)
        assert str(
            e.value
        ) == "Slice badplugin.badslice failed to start because: Too bad, this plugin is broken"

    config.server_enabled_extensions.set("")
    all = ibl._load_extensions()
    assert "badplugin" not in all
示例#13
0
async def migrate_v2_to_v3(hard_clean_db, hard_clean_db_post, postgresql_client: Connection, async_finalizer, server_config):
    # Get old tables
    with open(os.path.join(os.path.dirname(__file__), "dumps/v2.sql"), "r") as fh:
        await PGRestore(fh.readlines(), postgresql_client).run()

    ibl = InmantaBootloader()

    await ibl.start()
    yield
    await ibl.stop()
示例#14
0
async def migrate_v4_to_v5(
    hard_clean_db, hard_clean_db_post, postgresql_client: Connection, async_finalizer, server_config
) -> AsyncIterator[None]:
    # Get old tables
    with open(os.path.join(os.path.dirname(__file__), "dumps/v4.sql"), "r") as fh:
        await PGRestore(fh.readlines(), postgresql_client).run()

    ibl = InmantaBootloader()

    await ibl.start()
    # When the bootloader is started, it also executes the migration to v5
    yield
    await ibl.stop(timeout=15)
示例#15
0
async def test_server_logs_address(server_config, caplog):
    with caplog.at_level(logging.INFO):
        ibl = InmantaBootloader()
        await ibl.start()

        client = Client("client")
        result = await client.create_project("env-test")
        assert result.code == 200
        address = "127.0.0.1"

        await ibl.stop()
        log_contains(caplog, "protocol.rest", logging.INFO,
                     f"Server listening on {address}:")
def test_discover_and_load():
    with splice_extension_in("test_module_path"):

        config.server_enabled_extensions.set("testplugin")

        ibl = InmantaBootloader()
        print("plugins: ", ibl._discover_plugin_packages())

        assert "inmanta_ext.testplugin" in ibl._discover_plugin_packages()

        tpl = ibl._load_extension("inmanta_ext.testplugin")

        assert tpl == inmanta_ext.testplugin.extension.setup

        with pytest.raises(PluginLoadFailed):
            ibl._load_extension("inmanta_ext.noext")

        with pytest.raises(PluginLoadFailed):
            ibl._load_extension("inmanta_ext.noinit")
async def migrate_v202111260_to_v202203140(
        hard_clean_db, hard_clean_db_post, postgresql_client: Connection,
        server_config) -> AsyncIterator[Callable[[], Awaitable[None]]]:
    """
    Returns a callable that performs a v202111260 database restore and migrates to v202203140.
    """
    # Get old tables
    with open(os.path.join(os.path.dirname(__file__), "dumps/v202111260.sql"),
              "r") as fh:
        await PGRestore(fh.readlines(), postgresql_client).run()

    ibl = InmantaBootloader()

    # When the bootloader is started, it also executes the migration to v202203140
    yield ibl.start
    await ibl.stop(timeout=15)
async def test_server_status_database_down(server_config, server_pre_start,
                                           postgres_db,
                                           ensure_running_postgres_db_post,
                                           async_finalizer):
    ibl = InmantaBootloader()
    await ibl.start()
    async_finalizer.add(ibl.stop)
    postgres_db.stop()
    client = protocol.Client("client")
    result = await client.get_server_status()
    assert result.code == 200
    database_slice = None
    for slice in result.result["data"]["slices"]:
        if slice["name"] == "core.database":
            database_slice = slice
    assert database_slice
    assert not database_slice["status"]["connected"]
示例#19
0
async def migrate_v7_to_v17(hard_clean_db, hard_clean_db_post,
                            postgresql_client: Connection,
                            server_config) -> AsyncIterator[None]:
    """
    Performs a v7 database restore and migrates to v17.
    """
    # Get old tables
    with open(os.path.join(os.path.dirname(__file__), "dumps/v7.sql"),
              "r") as fh:
        await PGRestore(fh.readlines(), postgresql_client).run()

    ibl = InmantaBootloader()

    await ibl.start()
    # When the bootloader is started, it also executes the migration to v18
    yield
    await ibl.stop()
示例#20
0
async def migrate_v3_to_v4(hard_clean_db, hard_clean_db_post, postgresql_client: Connection, async_finalizer, server_config):
    # Get old tables
    with open(os.path.join(os.path.dirname(__file__), "dumps/v3.sql"), "r") as fh:
        await PGRestore(fh.readlines(), postgresql_client).run()

    for table_name in ["form", "formrecord", "resourceversionid"]:
        assert await does_table_exist(postgresql_client, table_name)

    result = await postgresql_client.fetch("SELECT action_id, resource_version_id FROM public.resourceversionid")
    resource_version_id_dict = defaultdict(list)
    for r in result:
        resource_version_id_dict[r["action_id"]].append(r["resource_version_id"])

    ibl = InmantaBootloader()

    # When the bootloader is started, it also executes the migration to v4
    await ibl.start()
    yield resource_version_id_dict
    await ibl.stop()
示例#21
0
async def server_multi(server_pre_start, event_loop, inmanta_config,
                       postgres_db, database_name, request, clean_reset,
                       unused_tcp_port_factory):
    """
    :param event_loop: explicitly include event_loop to make sure event loop started before and closed after this fixture.
    May not be required
    """
    state_dir = tempfile.mkdtemp()

    ssl, auth, ca = request.param

    path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")

    if auth:
        config.Config.set("server", "auth", "true")

    for x, ct in [
        ("server", None),
        ("agent_rest_transport", ["agent"]),
        ("compiler_rest_transport", ["compiler"]),
        ("client_rest_transport", ["api", "compiler"]),
        ("cmdline_rest_transport", ["api"]),
    ]:
        if ssl and not ca:
            config.Config.set(x, "ssl_cert_file",
                              os.path.join(path, "server.crt"))
            config.Config.set(x, "ssl_key_file",
                              os.path.join(path, "server.open.key"))
            config.Config.set(x, "ssl_ca_cert_file",
                              os.path.join(path, "server.crt"))
            config.Config.set(x, "ssl", "True")
        if ssl and ca:
            capath = os.path.join(path, "ca", "enduser-certs")

            config.Config.set(x, "ssl_cert_file",
                              os.path.join(capath, "server.crt"))
            config.Config.set(x, "ssl_key_file",
                              os.path.join(capath, "server.key.open"))
            config.Config.set(x, "ssl_ca_cert_file",
                              os.path.join(capath, "server.chain"))
            config.Config.set(x, "ssl", "True")
        if auth and ct is not None:
            token = protocol.encode_token(ct)
            config.Config.set(x, "token", token)

    port = str(unused_tcp_port_factory())
    config.Config.set("database", "name", database_name)
    config.Config.set("database", "host", "localhost")
    config.Config.set("database", "port", str(postgres_db.port))
    config.Config.set("database", "connection_timeout", str(3))
    config.Config.set("config", "state-dir", state_dir)
    config.Config.set("config", "log-dir", os.path.join(state_dir, "logs"))
    config.Config.set("agent_rest_transport", "port", port)
    config.Config.set("compiler_rest_transport", "port", port)
    config.Config.set("client_rest_transport", "port", port)
    config.Config.set("cmdline_rest_transport", "port", port)
    config.Config.set("server", "bind-port", port)
    config.Config.set("server", "bind-address", "127.0.0.1")
    config.Config.set("config", "executable",
                      os.path.abspath(inmanta.app.__file__))
    config.Config.set("server", "agent-timeout", "2")
    config.Config.set("agent", "agent-repair-interval", "0")
    config.Config.set("server", "auto-recompile-wait", "0")

    ibl = InmantaBootloader()

    try:
        await ibl.start()
    except SliceStartupException as e:
        port = config.Config.get("server", "bind-port")
        output = subprocess.check_output(["ss", "-antp"])
        output = output.decode("utf-8")
        logger.debug(f"Port: {port}")
        logger.debug(f"Port usage: \n {output}")
        raise e

    yield ibl.restserver
    try:
        await asyncio.wait_for(ibl.stop(), 15)
    except concurrent.futures.TimeoutError:
        logger.exception("Timeout during stop of the server in teardown")

    shutil.rmtree(state_dir)
示例#22
0
def get_product_meta_data() -> ProductMetadata:
    """Get the produce meta-data"""
    bootloader = InmantaBootloader()
    context = bootloader.load_slices()
    return context.get_product_metadata()
import pytest

from inmanta import config
from inmanta.server.bootloader import InmantaBootloader

logger = logging.getLogger(__name__)


@pytest.fixture
def {{ cookiecutter.extension_name }}_config(server_config, postgres_db, database_name):
    config.Config.set("server", "enabled_extensions", "{{ cookiecutter.extension_name }}")


@pytest.fixture
async def server({{ cookiecutter.extension_name }}_config, server_config):
    """
    Override standard inmanta server to allow more config to be injected
    """
    ibl = InmantaBootloader()
    await ibl.start()

    yield ibl.restserver

    try:
        await asyncio.wait_for(ibl.stop(), 15)
    except concurrent.futures.TimeoutError:
        logger.exception("Timeout during stop of the server in teardown")

    logger.info("Server clean up done")