def generate_ddc_project_compose(project: Project) -> Path:
    """This function is called every time ddc-project is run.
    It assembles a docker-compose file from the given configuration.
    It should execute as fast as possible.
    """
    project_compose_path = project.private_filepath("docker-compose.yml")
    template_path = DDC_PROJECT_TEMPLATE_PATH
    final_image = None
    if image_exists(project.image_name):
        final_image = project.image_name
    if not image_exists(project.requirements_image_name):
        logger.warning(f"Image {project.requirements_image_name} not found\n"
                       "Run\nderex build requirements\n to build it")

    openedx_customizations = project.get_openedx_customizations()

    tmpl = Template(template_path.read_text())
    text = tmpl.render(
        project=project,
        final_image=final_image,
        wsgi_py_path=WSGI_PY_PATH,
        derex_django_path=DEREX_DJANGO_PATH,
        openedx_customizations=openedx_customizations,
    )
    project_compose_path.write_text(text)
    return project_compose_path
def generate_ddc_test_compose(project: Project) -> Path:
    """This function assembles a docker-compose with test services for
    the given project.
    It should execute as fast as possible.
    """
    test_compose_path = project.private_filepath("docker-compose-test.yml")
    template_path = DDC_TEST_TEMPLATE_PATH

    tmpl = Template(template_path.read_text())
    text = tmpl.render(project=project)
    test_compose_path.write_text(text)
    return test_compose_path
Exemple #3
0
def test_docker_compose_addition_per_runmode(minimal_project, mocker, capsys):
    with minimal_project:
        docker_compose_debug_path = Project().root / "docker-compose-debug.yml"
        with docker_compose_debug_path.open("w") as fh:
            fh.write("lms:\n  image: foobar\n")
        project = Project()
        run_ddc_project([], project, dry_run=True)
        output = capsys.readouterr().out
        # The last option should be the path of the debug docker compose
        assert output.endswith(f"-f {docker_compose_debug_path}\n")

        project.runmode = ProjectRunMode.production
        default_project_docker_compose_file = project.private_filepath(
            "docker-compose.yml")
        run_ddc_project([], project, dry_run=True)
        output = capsys.readouterr().out
        # The last option should be the path of the project default docker compose file
        assert output.endswith(f"-f {default_project_docker_compose_file}\n")
Exemple #4
0
def generate_local_docker_compose(project: Project) -> Path:
    """This function is called every time ddc-project is run.
    It assembles a docker-compose file from the given configuration.
    It should execute as fast as possible.
    """
    local_compose_path = project.private_filepath("docker-compose.yml")
    template_path = abspath_from_egg("derex.runner",
                                     "derex/runner/templates/local.yml.j2")
    final_image = None
    if image_exists(project.image_tag):
        final_image = project.image_tag
    if not image_exists(project.requirements_image_tag):
        click.echo("Building requirements image")
        build_requirements_image(project)
    tmpl = Template(template_path.read_text())
    text = tmpl.render(project=project, final_image=final_image)
    local_compose_path.write_text(text)
    return local_compose_path
Exemple #5
0
def generate_local_docker_compose(project: Project) -> Path:
    """This function is called every time ddc-project is run.
    It assembles a docker-compose file from the given configuration.
    It should execute as fast as possible.
    """
    local_compose_path = project.private_filepath("docker-compose.yml")
    template_path = LOCAL_YML_J2_PATH
    final_image = None
    if image_exists(project.image_name):
        final_image = project.image_name
    if not image_exists(project.requirements_image_name):
        logger.warning(f"Image {project.requirements_image_name} not found\n"
                       "Run\nderex build requirements\n to build it")
    tmpl = Template(template_path.read_text())
    text = tmpl.render(project=project,
                       final_image=final_image,
                       wsgi_py_path=WSGI_PY_PATH)
    local_compose_path.write_text(text)
    return local_compose_path
Exemple #6
0
def generate_ddc_project_file(project: Project) -> Path:
    """This function is called every time ddc-project is run.
    It assembles a docker-compose file from the given configuration.
    It should execute as fast as possible.
    """
    project_compose_path = project.private_filepath("docker-compose.yml")
    template_path = DDC_PROJECT_TEMPLATE_PATH
    final_image = None
    if image_exists(project.image_name):
        final_image = project.image_name
    if not image_exists(project.requirements_image_name):
        logger.warning(f"Image {project.requirements_image_name} not found\n"
                       "Run\nderex build requirements\n to build it")

    openedx_customizations = []
    for openedx_customizations_dir in [
            DEREX_OPENEDX_CUSTOMIZATIONS_PATH / project.openedx_version.name,
            project.openedx_customizations_dir,
    ]:
        if openedx_customizations_dir and openedx_customizations_dir.exists():
            for python_file_path in openedx_customizations_dir.rglob("*.py"):
                openedx_customizations.append((
                    str(python_file_path),
                    str(python_file_path).replace(
                        str(openedx_customizations_dir),
                        "/openedx/edx-platform"),
                ))

    tmpl = Template(template_path.read_text())
    text = tmpl.render(
        project=project,
        final_image=final_image,
        wsgi_py_path=WSGI_PY_PATH,
        derex_django_path=DEREX_DJANGO_PATH,
        openedx_customizations=openedx_customizations,
    )
    project_compose_path.write_text(text)
    return project_compose_path
Exemple #7
0
def generate_local_docker_compose(project: Project) -> Path:
    """TODO: Interim function waiting to be refactored into derex.runner
    """
    local_compose_path = project.private_filepath(
        "docker-compose-discovery.yml")
    template_compose_path = abspath_from_egg(
        "derex.discovery", "derex/discovery/docker-compose-discovery.yml.j2")
    plugin_directories = project.get_plugin_directories(__package__)
    our_settings_dir = abspath_from_egg(
        "derex.discovery", "derex/discovery/settings/README.rst").parent

    settings_dir = our_settings_dir / "derex"
    active_settings = "base"

    if plugin_directories.get("settings"):
        settings_dir = plugin_directories.get("settings")

        if (plugin_directories.get("settings") /
                "{}.py".format(project.settings.name)).exists():
            active_settings = project.settings.name
        else:
            logger.warning(
                f"{project.settings.name} settings module not found for {__package__} plugin. "
                "Running with default settings.")

        # Write out default read-only settings file
        # if they are not present
        base_settings = settings_dir / "base.py"
        if not base_settings.is_file():
            base_settings.write_text("from .derex import *\n")

        init = settings_dir / "__init__.py"
        if not init.is_file():
            init.write_text('"""Settings for edX Discovery Service"""')

        for source_code in our_settings_dir.glob("**/*.py"):
            destination = settings_dir / source_code.relative_to(
                our_settings_dir)
            if (destination.is_file()
                    and destination.read_text() != source_code.read_text()):
                # TODO: Replace this warning with a call to a derex.runner
                # function which should take care of updating default settings
                logger.warning(
                    f"WARNING: Default settings modified at {destination}. Replacing "
                )
            if not destination.parent.is_dir():
                destination.parent.mkdir(parents=True)
            try:
                destination.write_text(source_code.read_text())
            except PermissionError:
                current_mode = stat.S_IMODE(os.lstat(destination).st_mode)
                # XXX Remove me: older versions of derex set a non-writable permission
                # for their files. This except branch is needed now (Easter 2020), but
                # when the pandemic is over we can probably remove it
                destination.chmod(current_mode | 0o700)
                destination.write_text(source_code.read_text())

    tmpl = Template(template_compose_path.read_text())
    text = tmpl.render(
        project=project,
        plugins_dirs=plugin_directories,
        settings_dir=settings_dir,
        active_settings=active_settings,
    )
    local_compose_path.write_text(text)
    return local_compose_path