Source code for openfactory.schemas.filelayer.local_backend

"""
LocalBackend configuration schema for OpenFactory applications.

This module defines the :class:`.LocalBackendConfig` class, which extends
:class:`.BaseBackendConfig` to configure local host directory backends.

Warning:
    The LocalBackend is primarily intended for development or testing purposes.
    It allows OpenFactory services to bind-mount a directory from the host filesystem
    into Docker containers. For production or network-shared storage, use networked
    backends (e.g., NFS or S3).

Note:
    - All paths are validated to be absolute and to exist on the host.
    - Mount points inside containers are normalized and restricted to safe characters.
    - This module only provides configuration and validation; it does not perform
      actual file operations.

.. admonition:: Usage Example

  To use the Local Storage Backend, add a `storage` entry to your OpenFactory YAML configuration file:

  .. code-block:: yaml

     storage:
       type: local
       local_path: /nfs/data
       mount_point: /mnt

.. seealso::

   The runtime class of the Local Backend is :class:`openfactory.filelayer.local_backend.LocalBackend`.
"""

import os
import re
from typing import Literal
from pydantic import Field, field_validator
from openfactory.schemas.filelayer.base_backend import BaseBackendConfig
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from openfactory.filelayer.local_backend import LocalBackend


[docs] class LocalBackendConfig(BaseBackendConfig): """ Configuration schema for LocalBackend. This backend is intended primarily for development or testing purposes. It allows OpenFactory services to bind-mount a local host directory into Docker containers. For production or network-shared storage, use networked backends. """ type: Literal["local"] = Field(description="Type of the backend") local_path: str = Field(..., description="Absolute path on the host machine") mount_point: str = Field(..., description="Mount point inside the container")
[docs] def create_backend_instance(self) -> "LocalBackend": """ Instantiate the runtime LocalBackend using this configuration. Returns: LocalBackend: Runtime backend instance. """ from openfactory.filelayer.local_backend import LocalBackend return LocalBackend(self)
[docs] @field_validator("local_path") def validate_path(cls, value: str) -> str: """ Validates that the host path exists and is a valid absolute path. Args: value (str): Path to validate. Returns: str: Normalized absolute path. Raises: ValueError: If the path is not absolute or does not exist on the host. """ value = value.strip() if not value.startswith("/"): raise ValueError("path must be an absolute path on the host") norm_path = os.path.normpath(value) if not os.path.exists(norm_path): raise ValueError(f"host path '{norm_path}' does not exist") if not os.path.isdir(norm_path): raise ValueError(f"host path '{norm_path}' must be a directory") return norm_path
[docs] @field_validator("mount_point", mode="before") def validate_mount_point(cls, value: str) -> str: """ Validates and normalizes the mount point inside the container. Args: value (str): Container mount point path. Returns: str: Normalized absolute path. Raises: ValueError: If the path is relative, contains '..', invalid chars, or too long. """ if ".." in value: raise ValueError("mount_point must not contain '..'") norm = os.path.normpath(value) if not norm.startswith("/"): raise ValueError("mount_point must be an absolute path inside the container") if re.search(r"[^a-zA-Z0-9._/-]", norm): raise ValueError("mount_point contains invalid characters") if len(norm) > 255: raise ValueError("mount_point is too long (max 255 chars)") return norm
model_config = { "extra": "forbid", "str_strip_whitespace": True }