Skip to content

Commit

Permalink
fix: Accommodate tests for lack of config.json file in the environment
Browse files Browse the repository at this point in the history
  • Loading branch information
khvn26 committed Apr 16, 2024
1 parent a5af729 commit 6fc6228
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 38 deletions.
6 changes: 3 additions & 3 deletions src/edge_proxy/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
map_traits_to_response_data,
)
from edge_proxy.models import IdentityWithTraits
from edge_proxy.settings import Settings
from edge_proxy.settings import AppSettings

logger = structlog.get_logger(__name__)

Expand All @@ -32,10 +32,10 @@ def __init__(
self,
cache: BaseEnvironmentsCache = None,
client: httpx.AsyncClient = None,
settings: Settings = None,
settings: AppSettings = None,
):
self.cache = cache or LocalMemEnvironmentsCache()
self.settings = settings or Settings()
self.settings = settings or AppSettings()
self._client = client or httpx.AsyncClient(
timeout=settings.api_poll_timeout_seconds,
)
Expand Down
2 changes: 1 addition & 1 deletion src/edge_proxy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ def serve():
)


def config():
def render_config():
ensure_defaults()
36 changes: 19 additions & 17 deletions src/edge_proxy/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@
from pydantic.env_settings import SettingsSourceCallable


CONFIG_PATH = os.environ.get(
"CONFIG_PATH",
default="config.json",
)


logger = structlog.get_logger()


class LogFormat(Enum):
GENERIC = "generic"
JSON = "json"
Expand All @@ -29,24 +38,18 @@ def to_logging_log_level(self) -> int:
return getattr(logging, self.value)


def get_config_path() -> str:
return os.environ.get("CONFIG_PATH", "config.json")


def ensure_defaults() -> None:
config_path = get_config_path()

if not os.path.exists(config_path):
defaults = _Settings()
if not os.path.exists(CONFIG_PATH):
defaults = AppSettings()
defaults_json = defaults.json(indent=4, exclude_none=True)
print(defaults_json, file=sys.stdout)
try:
with open(config_path, "w") as fp:
with open(CONFIG_PATH, "w") as fp:
fp.write(defaults_json)
except OSError:
structlog.get_logger().warning(
logger.warning(
"error_writing_config_defaults",
config_path=config_path,
config_path=CONFIG_PATH,
exc_info=True,
)

Expand All @@ -56,9 +59,8 @@ def json_config_settings_source(settings: BaseSettings) -> Dict[str, Any]:
A simple settings source that loads variables from a JSON file
at the project's root.
"""
config_path = get_config_path()
encoding = "utf-8"
return json.loads(Path(config_path).read_text(encoding))
return json.loads(Path(CONFIG_PATH).read_text(encoding))


class EnvironmentKeyPair(BaseModel):
Expand Down Expand Up @@ -89,7 +91,7 @@ class ServerSettings(BaseModel):
reload: bool = False


class _Settings(BaseModel):
class AppSettings(BaseModel):
environment_key_pairs: List[EnvironmentKeyPair] = [
EnvironmentKeyPair(
server_side_key="ser.environment_key",
Expand All @@ -111,7 +113,7 @@ class _Settings(BaseModel):
server: ServerSettings = ServerSettings()


class Settings(_Settings, BaseSettings):
class AppConfig(AppSettings, BaseSettings):
class Config:
@classmethod
def customise_sources(
Expand All @@ -123,5 +125,5 @@ def customise_sources(
return init_settings, env_settings, json_config_settings_source


def get_settings() -> Settings:
return Settings()
def get_settings() -> AppConfig:
return AppConfig()
10 changes: 8 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import typing

import pytest
from pytest_mock import MockerFixture
from fastapi.testclient import TestClient

from edge_proxy.server import app


@pytest.fixture
def environment_1_feature_states_response_list() -> typing.List[dict]:
Expand Down Expand Up @@ -36,7 +35,14 @@ def environment_1_feature_states_response_list_response_with_segment_override(
return environment_1_feature_states_response_list


@pytest.fixture(autouse=True)
def skip_json_config_settings_source(mocker: MockerFixture) -> None:
mocker.patch("edge_proxy.settings.json_config_settings_source", lambda _: {})


@pytest.fixture
def client():
from edge_proxy.server import app

with TestClient(app) as c:
yield c
8 changes: 4 additions & 4 deletions tests/test_environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
from edge_proxy.settings import (
EndpointCacheSettings,
EndpointCachesSettings,
Settings,
AppSettings,
)
from tests.fixtures.response_data import environment_1, environment_1_api_key

client_key_2 = "test_env_key_2"

settings = Settings(
settings = AppSettings(
api_url="http://127.0.0.1:8000/api/v1",
environment_key_pairs=[
{"server_side_key": "ser.key1", "client_side_key": environment_1_api_key},
Expand Down Expand Up @@ -142,7 +142,7 @@ async def test_refresh_environment_caches_clears_endpoint_caches_if_environment_
) -> None:
# Given
# we create a new settings object which includes caching settings
_settings = Settings(
_settings = AppSettings(
environment_key_pairs=[
{"client_side_key": environment_1_api_key, "server_side_key": "ser.key"}
],
Expand Down Expand Up @@ -199,7 +199,7 @@ async def test_get_identity_flags_response_skips_cache_for_different_identity(
) -> None:
# Given
# we create a new settings object which includes caching settings
_settings = Settings(
_settings = AppSettings(
environment_key_pairs=[
{"client_side_key": environment_1_api_key, "server_side_key": "ser.key"}
],
Expand Down
36 changes: 25 additions & 11 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@
from fastapi.testclient import TestClient
from pytest_mock import MockerFixture

from edge_proxy.server import app

from tests.fixtures.response_data import environment_1

client = TestClient(app)


@pytest.mark.parametrize("endpoint", ["/proxy/health", "/health"])
def test_health_check_returns_200_if_cache_was_updated_recently(
mocker: MockerFixture, endpoint: str
mocker: MockerFixture,
endpoint: str,
client: TestClient,
) -> None:
mocked_environment_service = mocker.patch("edge_proxy.server.environment_service")
mocked_environment_service.last_updated_at = datetime.now()
Expand All @@ -23,13 +21,18 @@ def test_health_check_returns_200_if_cache_was_updated_recently(
assert response.status_code == 200


def test_health_check_returns_500_if_cache_was_not_updated() -> None:
def test_health_check_returns_500_if_cache_was_not_updated(
client: TestClient,
) -> None:
response = client.get("/proxy/health")
assert response.status_code == 500
assert response.json() == {"status": "error"}


def test_health_check_returns_500_if_cache_is_stale(mocker) -> None:
def test_health_check_returns_500_if_cache_is_stale(
mocker: MockerFixture,
client: TestClient,
) -> None:
mocked_environment_service = mocker.patch("edge_proxy.server.environment_service")
mocked_environment_service.last_updated_at = datetime.now() - timedelta(days=10)
response = client.get("/proxy/health")
Expand All @@ -38,7 +41,9 @@ def test_health_check_returns_500_if_cache_is_stale(mocker) -> None:


def test_get_flags(
mocker: MockerFixture, environment_1_feature_states_response_list: list[dict]
mocker: MockerFixture,
environment_1_feature_states_response_list: list[dict],
client: TestClient,
) -> None:
environment_key = "test_environment_key"
mocked_environment_cache = mocker.patch(
Expand All @@ -53,7 +58,9 @@ def test_get_flags(


def test_get_flags_single_feature(
mocker: MockerFixture, environment_1_feature_states_response_list: list[dict]
mocker: MockerFixture,
environment_1_feature_states_response_list: list[dict],
client: TestClient,
) -> None:
environment_key = "test_environment_key"
mocked_environment_cache = mocker.patch(
Expand All @@ -71,6 +78,7 @@ def test_get_flags_single_feature(

def test_get_flags_single_feature__server_key_only_feature__return_expected(
mocker: MockerFixture,
client: TestClient,
) -> None:
# Given
environment_key = "test_environment_key"
Expand All @@ -94,7 +102,10 @@ def test_get_flags_single_feature__server_key_only_feature__return_expected(
}


def test_get_flags_unknown_key(mocker):
def test_get_flags_unknown_key(
mocker: MockerFixture,
client: TestClient,
):
environment_key = "unknown_environment_key"
mocked_environment_cache = mocker.patch(
"edge_proxy.server.environment_service.cache"
Expand All @@ -113,7 +124,9 @@ def test_get_flags_unknown_key(mocker):


def test_post_identity_with_traits(
mocker, environment_1_feature_states_response_list_response_with_segment_override
mocker,
environment_1_feature_states_response_list_response_with_segment_override,
client: TestClient,
):
environment_key = "test_environment_key"
mocked_environment_cache = mocker.patch(
Expand All @@ -138,6 +151,7 @@ def test_post_identity_with_traits(

def test_post_identity__invalid_trait_data__expected_response(
mocker: MockerFixture,
client: TestClient,
) -> None:
# Given
environment_key = "test_environment_key"
Expand Down

0 comments on commit 6fc6228

Please sign in to comment.