Skip to content

Commit

Permalink
feat(fal): rework container support and make depot default (#410)
Browse files Browse the repository at this point in the history
feat(fal): rework container support
  • Loading branch information
efiop authored Feb 12, 2025
1 parent 9a29db9 commit cd36d47
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
2 changes: 2 additions & 0 deletions projects/fal/src/fal/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def parse_key(cls, key: str, value: Any) -> tuple[Any, Any]:
# Conda environment definition should be parsed before sending to serverless
with open(value) as f:
return "env_dict", yaml.safe_load(f)
elif key == "image" and isinstance(value, ContainerImage):
return "image", value.to_dict()
else:
return key, value

Expand Down
46 changes: 38 additions & 8 deletions projects/fal/src/fal/container.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
from dataclasses import dataclass, field
from typing import Dict, Literal

Builder = Literal["depot", "service", "worker"]
BUILDERS = {"depot", "service", "worker"}
DEFAULT_BUILDER: Builder = "depot"


@dataclass
class ContainerImage:
"""ContainerImage represents a Docker image that can be built
from a Dockerfile.
"""

_known_keys = {"dockerfile_str", "build_args", "registries", "builder"}
dockerfile_str: str
build_args: Dict[str, str] = field(default_factory=dict)
registries: Dict[str, Dict[str, str]] = field(default_factory=dict)
builder: Builder = field(default=DEFAULT_BUILDER)

def __post_init__(self) -> None:
if self.registries:
for registry in self.registries.values():
keys = registry.keys()
if "username" not in keys or "password" not in keys:
raise ValueError(
"Username and password are required for each registry"
)

if self.builder not in BUILDERS:
raise ValueError(
f"Invalid builder: {self.builder}, must be one of {BUILDERS}"
)

@classmethod
def from_dockerfile_str(cls, text: str, **kwargs):
# Check for unknown keys and return them as a dict.
return dict(
dockerfile_str=text,
**{k: v for k, v in kwargs.items() if k in cls._known_keys},
)
def from_dockerfile_str(cls, text: str, **kwargs) -> "ContainerImage":
return cls(dockerfile_str=text, **kwargs)

@classmethod
def from_dockerfile(cls, path: str, **kwargs):
def from_dockerfile(cls, path: str, **kwargs) -> "ContainerImage":
with open(path) as fobj:
return cls.from_dockerfile_str(fobj.read(), **kwargs)

def to_dict(self) -> dict:
return {
"dockerfile_str": self.dockerfile_str,
"build_args": self.build_args,
"registries": self.registries,
"builder": self.builder,
}

0 comments on commit cd36d47

Please sign in to comment.