Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/common/core/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import logging
import os
import sys
import tempfile
import typing

from django.core.management import (
execute_from_command_line as django_execute_from_command_line,
)
from environs import Env

from common.core.cli import healthcheck
from common.core.utils import TemporaryDirectory

logger = logging.getLogger(__name__)

Expand All @@ -30,6 +31,7 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
main()
```
"""
env = Env()
ctx = contextlib.ExitStack()

# TODO @khvn26 Move logging setup to here
Expand All @@ -43,9 +45,11 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.dev")

# Set up Prometheus' multiprocess mode
if "PROMETHEUS_MULTIPROC_DIR" not in os.environ:
prometheus_multiproc_dir_name = tempfile.mkdtemp()

if not env.str("PROMETHEUS_MULTIPROC_DIR", ""):
delete = not env.bool("PROMETHEUS_MULTIPROC_DIR_KEEP", False)
prometheus_multiproc_dir_name = ctx.enter_context(
TemporaryDirectory(delete=delete)
)
logger.info(
"Created %s for Prometheus multi-process mode",
prometheus_multiproc_dir_name,
Expand Down
34 changes: 33 additions & 1 deletion src/common/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@
import logging
import pathlib
import random
import sys
import tempfile
from functools import lru_cache
from itertools import cycle
from typing import Iterator, Literal, NotRequired, TypedDict, TypeVar, get_args
from typing import (
Iterator,
Literal,
NotRequired,
TypedDict,
TypeVar,
get_args,
)

from django.conf import settings
from django.contrib.auth import get_user_model
Expand Down Expand Up @@ -186,3 +195,26 @@ def using_database_replica(
return manager

return manager.db_manager(chosen_replica)


if sys.version_info >= (3, 12):
# Already has the desired behavior; re-export for uniform imports.
TemporaryDirectory = tempfile.TemporaryDirectory
else:
import contextlib
from typing import ContextManager, Generator

def TemporaryDirectory(
suffix: str | None = None,
prefix: str | None = None,
dir: str | None = None,
delete: bool = True,
) -> ContextManager[str]:
if delete:
return tempfile.TemporaryDirectory(suffix, prefix, dir)

@contextlib.contextmanager
def _tmpdir() -> Generator[str, None, None]:
yield tempfile.mkdtemp(suffix, prefix, dir)

return _tmpdir()
29 changes: 29 additions & 0 deletions tests/integration/core/test_main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import os
from pathlib import Path

import django
import pytest
from django.core.management import ManagementUtility
from pyfakefs.fake_filesystem import FakeFilesystem
from pytest_httpserver import HTTPServer

from common.core.main import main
Expand Down Expand Up @@ -104,3 +108,28 @@ def test_main__healthcheck_http__server_invalid_response__runs_expected(
# When & Then
with pytest.raises(Exception):
main(argv)


def test_main__prometheus_multiproc_remove_dir_on_exit_default__expected() -> None:
# Given
os.environ.pop("PROMETHEUS_MULTIPROC_DIR_KEEP", None)

# When
main(["flagsmith"])

# Then
assert not Path(os.environ["PROMETHEUS_MULTIPROC_DIR"]).exists()


def test_main__prometheus_multiproc_remove_dir_on_exit_true__expected(
fs: FakeFilesystem,
) -> None:
# Given
os.environ.pop("PROMETHEUS_MULTIPROC_DIR", None)
os.environ["PROMETHEUS_MULTIPROC_DIR_KEEP"] = "true"

# When
main(["flagsmith"])

# Then
assert Path(os.environ["PROMETHEUS_MULTIPROC_DIR"]).exists()