Skip to content

Commit

Permalink
Add configuration entrypoint for ECS
Browse files Browse the repository at this point in the history
  • Loading branch information
karls committed Jul 10, 2023
1 parent daebe4b commit 7f22aa6
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 1 deletion.
16 changes: 16 additions & 0 deletions judoscale/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from collections import UserDict
from typing import Mapping

import requests

from judoscale.core.logger import logger

DEFAULTS = {"REPORT_INTERVAL_SECONDS": 10, "LOG_LEVEL": "WARN"}
Expand Down Expand Up @@ -49,6 +51,8 @@ def initialize(cls, env: Mapping = os.environ):
return cls.for_heroku(env)
elif env.get("RENDER_INSTANCE_ID"):
return cls.for_render(env)
elif env.get("ECS_CONTAINER_METADATA_URI_V4"):
return cls.for_ecs(env)
else:
return cls(None, "", env)

Expand All @@ -71,6 +75,18 @@ def for_render(cls, env: Mapping):
api_base_url = f"https://adapter.judoscale.com/api/{service_id}"
return cls(runtime_container, api_base_url, env)

@classmethod
def for_ecs(cls, env: Mapping):
container_metadata = requests.get(env["ECS_CONTAINER_METADATA_URI_V4"]).json()
service_name = container_metadata["DockerName"]
instance = container_metadata["DockerId"]

# All ECS containers have to be manually assigned as web instances,
# because ECS does not distinguish between web and worker instances.
runtime_container = RuntimeContainer(service_name, instance, "web")
api_base_url = env.get("JUDOSCALE_URL")
return cls(runtime_container, api_base_url, env)

@property
def is_enabled(self) -> bool:
return bool(self["API_BASE_URL"])
Expand Down
85 changes: 84 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ black = "^22.12.0"
isort = "^5.11.2"
flake8 = { version = "^6.0.0", python = ">=3.8.1,<4.0.0" }
pytest = "^7.2.2"
responses = "^0.23.1"

[tool.poetry.extras]
django = ["django"]
Expand Down
37 changes: 37 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import pytest
import responses

from judoscale.core.config import Config, RuntimeContainer

ecs_response = {
"DockerId": "b25c2505a33f4b3ab8673c3200c2f245-2750272591",
"DockerName": "backend",
}


@pytest.fixture
def mocked_responses():
with responses.RequestsMock() as rsps:
yield rsps


class TestConfig:
def test_on_heroku(self):
Expand Down Expand Up @@ -31,6 +45,29 @@ def test_on_render(self):
assert config["LOG_LEVEL"] == "WARN"
assert config["API_BASE_URL"] == "https://adapter.judoscale.com/api/srv-123"

def test_on_ecs(self, mocked_responses):
mocked_responses.get(
"https://127.0.0.1/api/123456",
status=200,
json=ecs_response,
)

fake_env = {
"ECS_CONTAINER_METADATA_URI_V4": "https://127.0.0.1/api/123456",
"JUDOSCALE_URL": "https://adapter.judoscale.com/api/srv-123",
"LOG_LEVEL": "WARN",
}
config = Config.for_ecs(fake_env)

assert config["RUNTIME_CONTAINER"].service_name == "backend"
assert (
config["RUNTIME_CONTAINER"].instance
== "b25c2505a33f4b3ab8673c3200c2f245-2750272591"
)
assert config["RUNTIME_CONTAINER"].service_type == "web"
assert config["LOG_LEVEL"] == "WARN"
assert config["API_BASE_URL"] == "https://adapter.judoscale.com/api/srv-123"

def test_is_enabled(self):
config = Config(None, "", {})
assert not config.is_enabled
Expand Down

0 comments on commit 7f22aa6

Please sign in to comment.