diff --git a/changes/9630.feature.md b/changes/9630.feature.md new file mode 100644 index 00000000000..dfafe078bfd --- /dev/null +++ b/changes/9630.feature.md @@ -0,0 +1 @@ +Add `ActionValidators` and `RBACValidators` dataclasses to inject RBAC validators through the dependency layer into processors diff --git a/src/ai/backend/manager/actions/validators/__init__.py b/src/ai/backend/manager/actions/validators/__init__.py index e69de29bb2d..ac5f278c63c 100644 --- a/src/ai/backend/manager/actions/validators/__init__.py +++ b/src/ai/backend/manager/actions/validators/__init__.py @@ -0,0 +1,8 @@ +from dataclasses import dataclass + +from .rbac import RBACValidators + + +@dataclass +class ActionValidators: + rbac: RBACValidators diff --git a/src/ai/backend/manager/actions/validators/rbac/__init__.py b/src/ai/backend/manager/actions/validators/rbac/__init__.py index e69de29bb2d..1f92880832d 100644 --- a/src/ai/backend/manager/actions/validators/rbac/__init__.py +++ b/src/ai/backend/manager/actions/validators/rbac/__init__.py @@ -0,0 +1,12 @@ +from dataclasses import dataclass + +from ai.backend.manager.actions.validators.rbac.scope import ScopeActionRBACValidator +from ai.backend.manager.actions.validators.rbac.single_entity import ( + SingleEntityActionRBACValidator, +) + + +@dataclass +class RBACValidators: + scope: ScopeActionRBACValidator + single_entity: SingleEntityActionRBACValidator diff --git a/src/ai/backend/manager/dependencies/processing/composer.py b/src/ai/backend/manager/dependencies/processing/composer.py index 1e03f5c53da..169db85ad8b 100644 --- a/src/ai/backend/manager/dependencies/processing/composer.py +++ b/src/ai/backend/manager/dependencies/processing/composer.py @@ -27,6 +27,12 @@ from ai.backend.manager.actions.monitors.audit_log import AuditLogMonitor from ai.backend.manager.actions.monitors.prometheus import PrometheusMonitor from ai.backend.manager.actions.monitors.reporter import ReporterMonitor +from ai.backend.manager.actions.validators import ActionValidators +from ai.backend.manager.actions.validators.rbac import RBACValidators +from ai.backend.manager.actions.validators.rbac.scope import ScopeActionRBACValidator +from ai.backend.manager.actions.validators.rbac.single_entity import ( + SingleEntityActionRBACValidator, +) from ai.backend.manager.agent_cache import AgentRPCCache from ai.backend.manager.clients.agent.pool import AgentClientPool from ai.backend.manager.clients.appproxy.client import AppProxyClientPool @@ -240,6 +246,12 @@ async def compose( registry_quota_service=setup_input.registry_quota_service, ) + permission_controller_repository = setup_input.repositories.permission_controller.repository + rbac_validators = RBACValidators( + scope=ScopeActionRBACValidator(permission_controller_repository), + single_entity=SingleEntityActionRBACValidator(permission_controller_repository), + ) + processors = await stack.enter_dependency( ProcessorsDependency(), ProcessorsProviderInput( @@ -247,6 +259,7 @@ async def compose( action_monitors=[reporter_monitor, prometheus_monitor, audit_log_monitor], event_hub=setup_input.event_hub, event_fetcher=setup_input.event_fetcher, + validators=ActionValidators(rbac=rbac_validators), ), ) diff --git a/src/ai/backend/manager/dependencies/processing/processors.py b/src/ai/backend/manager/dependencies/processing/processors.py index 013f8998a6f..d9d5d3745bc 100644 --- a/src/ai/backend/manager/dependencies/processing/processors.py +++ b/src/ai/backend/manager/dependencies/processing/processors.py @@ -8,6 +8,7 @@ from ai.backend.common.events.fetcher import EventFetcher from ai.backend.common.events.hub.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.processors import ProcessorArgs, Processors, ServiceArgs @@ -19,6 +20,7 @@ class ProcessorsProviderInput: action_monitors: list[ActionMonitor] event_hub: EventHub event_fetcher: EventFetcher + validators: ActionValidators class ProcessorsDependency(NonMonitorableDependencyProvider[ProcessorsProviderInput, Processors]): @@ -41,5 +43,6 @@ async def provide(self, setup_input: ProcessorsProviderInput) -> AsyncIterator[P event_fetcher=setup_input.event_fetcher, ), setup_input.action_monitors, + setup_input.validators, ) yield processors diff --git a/src/ai/backend/manager/services/agent/processors.py b/src/ai/backend/manager/services/agent/processors.py index a5869cc2440..e36fe4dedd9 100644 --- a/src/ai/backend/manager/services/agent/processors.py +++ b/src/ai/backend/manager/services/agent/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.agent.actions.get_total_resources import ( GetTotalResourcesAction, GetTotalResourcesActionResult, @@ -86,7 +87,12 @@ class AgentProcessors(AbstractProcessorPackage): LoadContainerCountsAction, LoadContainerCountsActionResult ] - def __init__(self, service: AgentService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: AgentService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.sync_agent_registry = ActionProcessor(service.sync_agent_registry, action_monitors) self.get_watcher_status = ActionProcessor(service.get_watcher_status, action_monitors) self.watcher_agent_start = ActionProcessor(service.watcher_agent_start, action_monitors) diff --git a/src/ai/backend/manager/services/app_config/processors.py b/src/ai/backend/manager/services/app_config/processors.py index d03d59c2efe..0868b55e5cf 100644 --- a/src/ai/backend/manager/services/app_config/processors.py +++ b/src/ai/backend/manager/services/app_config/processors.py @@ -7,6 +7,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( DeleteDomainConfigAction, @@ -43,7 +44,12 @@ class AppConfigProcessors(AbstractProcessorPackage): # Merged config processor get_merged_config: ActionProcessor[GetMergedAppConfigAction, GetMergedAppConfigActionResult] - def __init__(self, service: AppConfigService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: AppConfigService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: # Domain config processors self.get_domain_config = ActionProcessor(service.get_domain_config, action_monitors) self.upsert_domain_config = ActionProcessor(service.upsert_domain_config, action_monitors) diff --git a/src/ai/backend/manager/services/artifact/processors.py b/src/ai/backend/manager/services/artifact/processors.py index 6d6fc38acad..02900ed66a9 100644 --- a/src/ai/backend/manager/services/artifact/processors.py +++ b/src/ai/backend/manager/services/artifact/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.artifact.actions.delegate_scan import ( DelegateScanArtifactsAction, DelegateScanArtifactsActionResult, @@ -81,7 +82,12 @@ class ArtifactProcessors(AbstractProcessorPackage): delegate_scan: ActionProcessor[DelegateScanArtifactsAction, DelegateScanArtifactsActionResult] - def __init__(self, service: ArtifactService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ArtifactService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: # TODO: Move scan action to ArtifactRegistryService self.scan = ActionProcessor(service.scan, action_monitors) self.get = ActionProcessor(service.get, action_monitors) diff --git a/src/ai/backend/manager/services/artifact_registry/processors.py b/src/ai/backend/manager/services/artifact_registry/processors.py index 9444c611735..07d825b472d 100644 --- a/src/ai/backend/manager/services/artifact_registry/processors.py +++ b/src/ai/backend/manager/services/artifact_registry/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.artifact_registry.actions.common.get_meta import ( GetArtifactRegistryMetaAction, GetArtifactRegistryMetaActionResult, @@ -129,7 +130,10 @@ class ArtifactRegistryProcessors(AbstractProcessorPackage): ] def __init__( - self, service: ArtifactRegistryService, action_monitors: list[ActionMonitor] + self, + service: ArtifactRegistryService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_huggingface_registry = ActionProcessor( service.create_huggingface_registry, action_monitors diff --git a/src/ai/backend/manager/services/artifact_revision/processors.py b/src/ai/backend/manager/services/artifact_revision/processors.py index c3c909a9fbb..40ff3879408 100644 --- a/src/ai/backend/manager/services/artifact_revision/processors.py +++ b/src/ai/backend/manager/services/artifact_revision/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.artifact_revision.actions.approve import ( ApproveArtifactRevisionAction, ApproveArtifactRevisionActionResult, @@ -91,7 +92,10 @@ class ArtifactRevisionProcessors(AbstractProcessorPackage): ] def __init__( - self, service: ArtifactRevisionService, action_monitors: list[ActionMonitor] + self, + service: ArtifactRevisionService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.get = ActionProcessor(service.get, action_monitors) self.get_readme = ActionProcessor(service.get_readme, action_monitors) diff --git a/src/ai/backend/manager/services/audit_log/processors.py b/src/ai/backend/manager/services/audit_log/processors.py index 8cc07c8a7f4..2936cdd3832 100644 --- a/src/ai/backend/manager/services/audit_log/processors.py +++ b/src/ai/backend/manager/services/audit_log/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.audit_log.actions.create import ( CreateAuditLogAction, CreateAuditLogActionResult, @@ -20,7 +21,12 @@ class AuditLogProcessors(AbstractProcessorPackage): create: ActionProcessor[CreateAuditLogAction, CreateAuditLogActionResult] search: ActionProcessor[SearchAuditLogsAction, SearchAuditLogsActionResult] - def __init__(self, service: AuditLogService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: AuditLogService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create = ActionProcessor(service.create, action_monitors) self.search = ActionProcessor(service.search, action_monitors) diff --git a/src/ai/backend/manager/services/auth/processors.py b/src/ai/backend/manager/services/auth/processors.py index 6ca8e690a49..b2425e649df 100644 --- a/src/ai/backend/manager/services/auth/processors.py +++ b/src/ai/backend/manager/services/auth/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.auth.actions.authorize import ( AuthorizeAction, AuthorizeActionResult, @@ -63,7 +64,12 @@ class AuthProcessors(AbstractProcessorPackage): ] resolve_user_scope: ActionProcessor[ResolveUserScopeAction, ResolveUserScopeResult] - def __init__(self, service: AuthService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: AuthService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.signout = ActionProcessor(service.signout, action_monitors) self.update_full_name = ActionProcessor(service.update_full_name, action_monitors) self.get_ssh_keypair = ActionProcessor(service.get_ssh_keypair, action_monitors) diff --git a/src/ai/backend/manager/services/container_registry/processors.py b/src/ai/backend/manager/services/container_registry/processors.py index 18c0caaf227..2d4a0589cc5 100644 --- a/src/ai/backend/manager/services/container_registry/processors.py +++ b/src/ai/backend/manager/services/container_registry/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.container_registry.actions.clear_images import ( ClearImagesAction, ClearImagesActionResult, @@ -101,7 +102,10 @@ class ContainerRegistryProcessors(AbstractProcessorPackage): ] def __init__( - self, service: ContainerRegistryService, action_monitors: list[ActionMonitor] + self, + service: ContainerRegistryService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.rescan_images = ActionProcessor(service.rescan_images, action_monitors) self.clear_images = ActionProcessor(service.clear_images, action_monitors) diff --git a/src/ai/backend/manager/services/deployment/processors.py b/src/ai/backend/manager/services/deployment/processors.py index eb021ba1360..91f84d90cb1 100644 --- a/src/ai/backend/manager/services/deployment/processors.py +++ b/src/ai/backend/manager/services/deployment/processors.py @@ -7,6 +7,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.deployment.actions.access_token.create_access_token import ( CreateAccessTokenAction, CreateAccessTokenActionResult, @@ -169,7 +170,12 @@ class DeploymentProcessors(AbstractProcessorPackage): create_access_token: ActionProcessor[CreateAccessTokenAction, CreateAccessTokenActionResult] search_access_tokens: ActionProcessor[SearchAccessTokensAction, SearchAccessTokensActionResult] - def __init__(self, service: DeploymentService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: DeploymentService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: # Deployment CRUD self.create_deployment = ActionProcessor(service.create_deployment, action_monitors) self.create_legacy_deployment = ActionProcessor( diff --git a/src/ai/backend/manager/services/domain/processors.py b/src/ai/backend/manager/services/domain/processors.py index 544964b43f8..b3a4d318b93 100644 --- a/src/ai/backend/manager/services/domain/processors.py +++ b/src/ai/backend/manager/services/domain/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.domain.actions.create_domain import ( CreateDomainAction, CreateDomainActionResult, @@ -54,7 +55,12 @@ class DomainProcessors(AbstractProcessorPackage): search_domains: ActionProcessor[SearchDomainsAction, SearchDomainsActionResult] search_rg_domains: ActionProcessor[SearchRGDomainsAction, SearchRGDomainsActionResult] - def __init__(self, service: DomainService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: DomainService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_domain_node = ActionProcessor(service.create_domain_node, action_monitors) self.modify_domain_node = ActionProcessor(service.modify_domain_node, action_monitors) self.create_domain = ActionProcessor(service.create_domain, action_monitors) diff --git a/src/ai/backend/manager/services/dotfile/processors.py b/src/ai/backend/manager/services/dotfile/processors.py index 091229ab7b4..5cb9944a6fa 100644 --- a/src/ai/backend/manager/services/dotfile/processors.py +++ b/src/ai/backend/manager/services/dotfile/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions.check_group_membership import ( CheckGroupMembershipAction, @@ -38,7 +39,12 @@ class DotfileProcessors(AbstractProcessorPackage): UpdateBootstrapScriptAction, UpdateBootstrapScriptActionResult ] - def __init__(self, service: DotfileService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: DotfileService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create = ActionProcessor(service.create_dotfile, action_monitors) self.list_or_get = ActionProcessor(service.list_or_get_dotfiles, action_monitors) self.update = ActionProcessor(service.update_dotfile, action_monitors) diff --git a/src/ai/backend/manager/services/error_log/processors.py b/src/ai/backend/manager/services/error_log/processors.py index 7951ec8692e..072802b5dc2 100644 --- a/src/ai/backend/manager/services/error_log/processors.py +++ b/src/ai/backend/manager/services/error_log/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import CreateErrorLogAction, CreateErrorLogActionResult from .actions.list import ListErrorLogsAction, ListErrorLogsActionResult @@ -23,7 +24,12 @@ class ErrorLogProcessors(AbstractProcessorPackage): list_logs: ActionProcessor[ListErrorLogsAction, ListErrorLogsActionResult] mark_cleared: ActionProcessor[MarkClearedErrorLogAction, MarkClearedErrorLogActionResult] - def __init__(self, service: ErrorLogService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ErrorLogService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create = ActionProcessor(service.create, action_monitors) self.search = ActionProcessor(service.search, action_monitors) self.list_logs = ActionProcessor(service.list_logs, action_monitors) diff --git a/src/ai/backend/manager/services/etcd_config/processors.py b/src/ai/backend/manager/services/etcd_config/processors.py index 2849109e2cc..663feaed8c8 100644 --- a/src/ai/backend/manager/services/etcd_config/processors.py +++ b/src/ai/backend/manager/services/etcd_config/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions.delete_config import DeleteConfigAction, DeleteConfigActionResult from .actions.get_config import GetConfigAction, GetConfigActionResult @@ -32,7 +33,12 @@ class EtcdConfigProcessors(AbstractProcessorPackage): set_config: ActionProcessor[SetConfigAction, SetConfigActionResult] delete_config: ActionProcessor[DeleteConfigAction, DeleteConfigActionResult] - def __init__(self, service: EtcdConfigService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: EtcdConfigService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.get_resource_slots = ActionProcessor(service.get_resource_slots, action_monitors) self.get_resource_metadata = ActionProcessor(service.get_resource_metadata, action_monitors) self.get_vfolder_types = ActionProcessor(service.get_vfolder_types, action_monitors) diff --git a/src/ai/backend/manager/services/export/processors.py b/src/ai/backend/manager/services/export/processors.py index 38f3095308a..9c132733c55 100644 --- a/src/ai/backend/manager/services/export/processors.py +++ b/src/ai/backend/manager/services/export/processors.py @@ -7,6 +7,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( ExportAuditLogsCSVAction, @@ -46,7 +47,12 @@ class ExportProcessors(AbstractProcessorPackage): export_keypairs_csv: ActionProcessor[ExportKeypairsCSVAction, ExportKeypairsCSVActionResult] export_audit_logs_csv: ActionProcessor[ExportAuditLogsCSVAction, ExportAuditLogsCSVActionResult] - def __init__(self, service: ExportService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ExportService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.list_reports = ActionProcessor(service.list_reports, action_monitors) self.get_report = ActionProcessor(service.get_report, action_monitors) self.export_users_csv = ActionProcessor(service.export_users_csv, action_monitors) diff --git a/src/ai/backend/manager/services/fair_share/processors.py b/src/ai/backend/manager/services/fair_share/processors.py index 57e85818715..898b958948e 100644 --- a/src/ai/backend/manager/services/fair_share/processors.py +++ b/src/ai/backend/manager/services/fair_share/processors.py @@ -7,6 +7,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( BulkUpsertDomainFairShareWeightAction, @@ -99,7 +100,12 @@ class FairShareProcessors(AbstractProcessorPackage): BulkUpsertUserFairShareWeightAction, BulkUpsertUserFairShareWeightActionResult ] - def __init__(self, service: FairShareService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: FairShareService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: # Domain Fair Share self.get_domain_fair_share = ActionProcessor(service.get_domain_fair_share, action_monitors) self.search_domain_fair_shares = ActionProcessor( diff --git a/src/ai/backend/manager/services/group/processors.py b/src/ai/backend/manager/services/group/processors.py index ce180a5d389..3c79cf1a568 100644 --- a/src/ai/backend/manager/services/group/processors.py +++ b/src/ai/backend/manager/services/group/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.group.actions.create_group import ( CreateGroupAction, CreateGroupActionResult, @@ -52,7 +53,12 @@ class GroupProcessors(AbstractProcessorPackage): search_projects_by_user: ActionProcessor[SearchProjectsByUserAction, SearchProjectsActionResult] get_project: ActionProcessor[GetProjectAction, GetProjectActionResult] - def __init__(self, group_service: GroupService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + group_service: GroupService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_group = ActionProcessor(group_service.create_group, action_monitors) self.modify_group = ActionProcessor(group_service.modify_group, action_monitors) self.delete_group = ActionProcessor(group_service.delete_group, action_monitors) diff --git a/src/ai/backend/manager/services/image/processors.py b/src/ai/backend/manager/services/image/processors.py index 81117f4b38c..004ebf54d40 100644 --- a/src/ai/backend/manager/services/image/processors.py +++ b/src/ai/backend/manager/services/image/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.image.actions.alias_image import ( AliasImageAction, AliasImageActionResult, @@ -126,7 +127,12 @@ class ImageProcessors(AbstractProcessorPackage): search_images: ActionProcessor[SearchImagesAction, SearchImagesActionResult] search_aliases: ActionProcessor[SearchAliasesAction, SearchAliasesActionResult] - def __init__(self, service: ImageService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ImageService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.get_image_installed_agents = ActionProcessor( service.get_image_installed_agents, action_monitors ) diff --git a/src/ai/backend/manager/services/keypair_resource_policy/processors.py b/src/ai/backend/manager/services/keypair_resource_policy/processors.py index 17de40a7801..2c5506699dc 100644 --- a/src/ai/backend/manager/services/keypair_resource_policy/processors.py +++ b/src/ai/backend/manager/services/keypair_resource_policy/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.keypair_resource_policy.actions.create_keypair_resource_policy import ( CreateKeyPairResourcePolicyAction, CreateKeyPairResourcePolicyActionResult, @@ -32,7 +33,10 @@ class KeypairResourcePolicyProcessors(AbstractProcessorPackage): ] def __init__( - self, service: KeypairResourcePolicyService, action_monitors: list[ActionMonitor] + self, + service: KeypairResourcePolicyService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_keypair_resource_policy = ActionProcessor( service.create_keypair_resource_policy, action_monitors diff --git a/src/ai/backend/manager/services/manager_admin/processors.py b/src/ai/backend/manager/services/manager_admin/processors.py index 3b9add29345..8468be2477c 100644 --- a/src/ai/backend/manager/services/manager_admin/processors.py +++ b/src/ai/backend/manager/services/manager_admin/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions.fetch_status import FetchManagerStatusAction, FetchManagerStatusActionResult from .actions.get_announcement import GetAnnouncementAction, GetAnnouncementActionResult @@ -32,7 +33,12 @@ class ManagerAdminProcessors(AbstractProcessorPackage): ] get_db_cxn_status: ActionProcessor[GetDbCxnStatusAction, GetDbCxnStatusActionResult] - def __init__(self, service: ManagerAdminService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ManagerAdminService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.fetch_status = ActionProcessor(service.fetch_status, action_monitors) self.update_status = ActionProcessor(service.update_status, action_monitors) self.get_announcement = ActionProcessor(service.get_announcement, action_monitors) diff --git a/src/ai/backend/manager/services/metric/processors/utilization_metric.py b/src/ai/backend/manager/services/metric/processors/utilization_metric.py index 2203e354a58..b571a128358 100644 --- a/src/ai/backend/manager/services/metric/processors/utilization_metric.py +++ b/src/ai/backend/manager/services/metric/processors/utilization_metric.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.metric.actions.container import ( ContainerMetricAction, ContainerMetricActionResult, @@ -19,7 +20,10 @@ class UtilizationMetricProcessors(AbstractProcessorPackage): ] def __init__( - self, service: UtilizationMetricService, action_monitors: list[ActionMonitor] + self, + service: UtilizationMetricService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.query_container = ActionProcessor(service.container.query_metric, action_monitors) self.query_container_metadata = ActionProcessor( diff --git a/src/ai/backend/manager/services/model_serving/processors/auto_scaling.py b/src/ai/backend/manager/services/model_serving/processors/auto_scaling.py index cba4ebe24c9..73b6d0fc055 100644 --- a/src/ai/backend/manager/services/model_serving/processors/auto_scaling.py +++ b/src/ai/backend/manager/services/model_serving/processors/auto_scaling.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.model_serving.actions.create_auto_scaling_rule import ( CreateEndpointAutoScalingRuleAction, CreateEndpointAutoScalingRuleActionResult, @@ -36,7 +37,12 @@ class ModelServingAutoScalingProcessors(AbstractProcessorPackage): ModifyEndpointAutoScalingRuleAction, ModifyEndpointAutoScalingRuleActionResult ] - def __init__(self, service: AutoScalingService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: AutoScalingService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.scale_service_replicas = ActionProcessor( service.scale_service_replicas, action_monitors ) diff --git a/src/ai/backend/manager/services/model_serving/processors/model_serving.py b/src/ai/backend/manager/services/model_serving/processors/model_serving.py index 313ad03385d..1a382e7ff8f 100644 --- a/src/ai/backend/manager/services/model_serving/processors/model_serving.py +++ b/src/ai/backend/manager/services/model_serving/processors/model_serving.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.model_serving.actions.clear_error import ( ClearErrorAction, ClearErrorActionResult, @@ -88,6 +89,7 @@ def __init__( self, service: ModelServingService, action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_model_service = ActionProcessor(service.create, action_monitors) self.list_model_service = ActionProcessor(service.list_serve, action_monitors) diff --git a/src/ai/backend/manager/services/notification/processors.py b/src/ai/backend/manager/services/notification/processors.py index 0ada28780ed..acb54b98e4f 100644 --- a/src/ai/backend/manager/services/notification/processors.py +++ b/src/ai/backend/manager/services/notification/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( CreateChannelAction, @@ -56,7 +57,12 @@ class NotificationProcessors(AbstractProcessorPackage): ProcessNotificationAction, ProcessNotificationActionResult ] - def __init__(self, service: NotificationService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: NotificationService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_channel = ActionProcessor(service.create_channel, action_monitors) self.search_channels = ActionProcessor(service.search_channels, action_monitors) self.get_channel = ActionProcessor(service.get_channel, action_monitors) diff --git a/src/ai/backend/manager/services/object_storage/processors.py b/src/ai/backend/manager/services/object_storage/processors.py index 17f6524919e..84110b29d3c 100644 --- a/src/ai/backend/manager/services/object_storage/processors.py +++ b/src/ai/backend/manager/services/object_storage/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.object_storage.actions.create import ( CreateObjectStorageAction, CreateObjectStorageActionResult, @@ -54,7 +55,12 @@ class ObjectStorageProcessors(AbstractProcessorPackage): SearchObjectStoragesAction, SearchObjectStoragesActionResult ] - def __init__(self, service: ObjectStorageService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ObjectStorageService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create = ActionProcessor(service.create, action_monitors) self.update = ActionProcessor(service.update, action_monitors) self.delete = ActionProcessor(service.delete, action_monitors) diff --git a/src/ai/backend/manager/services/permission_contoller/processors.py b/src/ai/backend/manager/services/permission_contoller/processors.py index 5131e172ad0..bfb68d05e24 100644 --- a/src/ai/backend/manager/services/permission_contoller/processors.py +++ b/src/ai/backend/manager/services/permission_contoller/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( AssignRoleAction, @@ -97,7 +98,10 @@ class PermissionControllerProcessors(AbstractProcessorPackage): delete_permission: ActionProcessor[DeletePermissionAction, DeletePermissionActionResult] def __init__( - self, service: PermissionControllerService, action_monitors: list[ActionMonitor] + self, + service: PermissionControllerService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_role = ActionProcessor(service.create_role, action_monitors) self.update_role = ActionProcessor(service.update_role, action_monitors) diff --git a/src/ai/backend/manager/services/processors.py b/src/ai/backend/manager/services/processors.py index 2df4f2fc902..0d92b494bdb 100644 --- a/src/ai/backend/manager/services/processors.py +++ b/src/ai/backend/manager/services/processors.py @@ -16,6 +16,7 @@ from ai.backend.common.plugin.monitor import ErrorPluginContext from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.agent_cache import AgentRPCCache from ai.backend.manager.clients.appproxy.client import AppProxyClientPool from ai.backend.manager.config.provider import ManagerConfigProvider @@ -557,89 +558,116 @@ class Processors(AbstractProcessorPackage): events: EventsProcessors @classmethod - def create(cls, args: ProcessorArgs, action_monitors: list[ActionMonitor]) -> Self: + def create( + cls, + args: ProcessorArgs, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> Self: services = Services.create(args.service_args) - agent_processors = AgentProcessors(services.agent, action_monitors) - app_config_processors = AppConfigProcessors(services.app_config, action_monitors) - domain_processors = DomainProcessors(services.domain, action_monitors) - dotfile_processors = DotfileProcessors(services.dotfile, action_monitors) - error_log_processors = ErrorLogProcessors(services.error_log, action_monitors) - etcd_config_processors = EtcdConfigProcessors(services.etcd_config, action_monitors) - export_processors = ExportProcessors(services.export, action_monitors) - fair_share_processors = FairShareProcessors(services.fair_share, action_monitors) - group_processors = GroupProcessors(services.group, action_monitors) - user_processors = UserProcessors(services.user, action_monitors) - image_processors = ImageProcessors(services.image, action_monitors) + agent_processors = AgentProcessors(services.agent, action_monitors, validators) + app_config_processors = AppConfigProcessors( + services.app_config, action_monitors, validators + ) + domain_processors = DomainProcessors(services.domain, action_monitors, validators) + dotfile_processors = DotfileProcessors(services.dotfile, action_monitors, validators) + error_log_processors = ErrorLogProcessors(services.error_log, action_monitors, validators) + etcd_config_processors = EtcdConfigProcessors( + services.etcd_config, action_monitors, validators + ) + export_processors = ExportProcessors(services.export, action_monitors, validators) + fair_share_processors = FairShareProcessors( + services.fair_share, action_monitors, validators + ) + group_processors = GroupProcessors(services.group, action_monitors, validators) + user_processors = UserProcessors(services.user, action_monitors, validators) + image_processors = ImageProcessors(services.image, action_monitors, validators) container_registry_processors = ContainerRegistryProcessors( - services.container_registry, action_monitors + services.container_registry, action_monitors, validators + ) + vfolder_processors = VFolderProcessors(services.vfolder, action_monitors, validators) + vfolder_file_processors = VFolderFileProcessors( + services.vfolder_file, action_monitors, validators ) - vfolder_processors = VFolderProcessors(services.vfolder, action_monitors) - vfolder_file_processors = VFolderFileProcessors(services.vfolder_file, action_monitors) vfolder_invite_processors = VFolderInviteProcessors( - services.vfolder_invite, action_monitors + services.vfolder_invite, action_monitors, validators ) vfolder_sharing_processors = VFolderSharingProcessors( - services.vfolder_sharing, action_monitors + services.vfolder_sharing, action_monitors, validators ) - session_processors = SessionProcessors(services.session, action_monitors) + session_processors = SessionProcessors(services.session, action_monitors, validators) keypair_resource_policy_processors = KeypairResourcePolicyProcessors( - services.keypair_resource_policy, action_monitors + services.keypair_resource_policy, action_monitors, validators + ) + manager_admin_processors = ManagerAdminProcessors( + services.manager_admin, action_monitors, validators ) - manager_admin_processors = ManagerAdminProcessors(services.manager_admin, action_monitors) user_resource_policy_processors = UserResourcePolicyProcessors( - services.user_resource_policy, action_monitors + services.user_resource_policy, action_monitors, validators ) project_resource_policy_processors = ProjectResourcePolicyProcessors( - services.project_resource_policy, action_monitors + services.project_resource_policy, action_monitors, validators ) prometheus_query_preset_processors = PrometheusQueryPresetProcessors( - services.prometheus_query_preset, action_monitors + services.prometheus_query_preset, action_monitors, validators ) resource_preset_processors = ResourcePresetProcessors( - services.resource_preset, action_monitors + services.resource_preset, action_monitors, validators + ) + resource_slot_processors = ResourceSlotProcessors( + services.resource_slot, action_monitors, validators ) - resource_slot_processors = ResourceSlotProcessors(services.resource_slot, action_monitors) resource_usage_processors = ResourceUsageProcessors( - services.resource_usage, action_monitors + services.resource_usage, action_monitors, validators + ) + scaling_group_processors = ScalingGroupProcessors( + services.scaling_group, action_monitors, validators + ) + model_serving_processors = ModelServingProcessors( + services.model_serving, action_monitors, validators ) - scaling_group_processors = ScalingGroupProcessors(services.scaling_group, action_monitors) - model_serving_processors = ModelServingProcessors(services.model_serving, action_monitors) model_serving_auto_scaling_processors = ModelServingAutoScalingProcessors( - services.model_serving_auto_scaling, action_monitors + services.model_serving_auto_scaling, action_monitors, validators ) utilization_metric_processors = UtilizationMetricProcessors( - services.utilization_metric, action_monitors + services.utilization_metric, action_monitors, validators + ) + auth = AuthProcessors(services.auth, action_monitors, validators) + notification_processors = NotificationProcessors( + services.notification, action_monitors, validators ) - auth = AuthProcessors(services.auth, action_monitors) - notification_processors = NotificationProcessors(services.notification, action_monitors) permission_controller_processors = PermissionControllerProcessors( - services.permission_controller, action_monitors + services.permission_controller, action_monitors, validators ) object_storage_processors = ObjectStorageProcessors( - services.object_storage, action_monitors + services.object_storage, action_monitors, validators ) - vfs_storage_processors = VFSStorageProcessors(services.vfs_storage, action_monitors) - artifact_processors = ArtifactProcessors(services.artifact, action_monitors) + vfs_storage_processors = VFSStorageProcessors( + services.vfs_storage, action_monitors, validators + ) + artifact_processors = ArtifactProcessors(services.artifact, action_monitors, validators) artifact_registry_processors = ArtifactRegistryProcessors( - services.artifact_registry, action_monitors + services.artifact_registry, action_monitors, validators ) artifact_revision_processors = ArtifactRevisionProcessors( - services.artifact_revision, action_monitors + services.artifact_revision, action_monitors, validators ) - deployment_processors = DeploymentProcessors(services.deployment, action_monitors) + deployment_processors = DeploymentProcessors( + services.deployment, action_monitors, validators + ) storage_namespace_processors = StorageNamespaceProcessors( - services.storage_namespace, action_monitors + services.storage_namespace, action_monitors, validators ) - audit_log_processors = AuditLogProcessors(services.audit_log, []) + audit_log_processors = AuditLogProcessors(services.audit_log, [], validators) scheduling_history_processors = SchedulingHistoryProcessors( - services.scheduling_history, action_monitors + services.scheduling_history, action_monitors, validators ) service_catalog_processors = ServiceCatalogProcessors( - services.service_catalog, action_monitors + services.service_catalog, action_monitors, validators ) - template_processors = TemplateProcessors(services.template, action_monitors) + template_processors = TemplateProcessors(services.template, action_monitors, validators) stream_processors = StreamProcessors(services.stream, action_monitors) events_processors = EventsProcessors( services.events, diff --git a/src/ai/backend/manager/services/project_resource_policy/processors.py b/src/ai/backend/manager/services/project_resource_policy/processors.py index 2e73acd1b01..864a34f9899 100644 --- a/src/ai/backend/manager/services/project_resource_policy/processors.py +++ b/src/ai/backend/manager/services/project_resource_policy/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.project_resource_policy.actions.create_project_resource_policy import ( CreateProjectResourcePolicyAction, CreateProjectResourcePolicyActionResult, @@ -30,7 +31,10 @@ class ProjectResourcePolicyProcessors(AbstractProcessorPackage): ] def __init__( - self, service: ProjectResourcePolicyService, action_monitors: list[ActionMonitor] + self, + service: ProjectResourcePolicyService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_project_resource_policy = ActionProcessor( service.create_project_resource_policy, action_monitors diff --git a/src/ai/backend/manager/services/prometheus_query_preset/processors.py b/src/ai/backend/manager/services/prometheus_query_preset/processors.py index ecdfd05e589..65000deaef1 100644 --- a/src/ai/backend/manager/services/prometheus_query_preset/processors.py +++ b/src/ai/backend/manager/services/prometheus_query_preset/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.prometheus_query_preset.actions import ( CreatePresetAction, CreatePresetActionResult, @@ -31,7 +32,10 @@ class PrometheusQueryPresetProcessors(AbstractProcessorPackage): execute_preset: ActionProcessor[ExecutePresetAction, ExecutePresetActionResult] def __init__( - self, service: PrometheusQueryPresetService, action_monitors: list[ActionMonitor] + self, + service: PrometheusQueryPresetService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_preset = ActionProcessor(service.create_preset, action_monitors) self.get_preset = ActionProcessor(service.get_preset, action_monitors) diff --git a/src/ai/backend/manager/services/resource_preset/processors.py b/src/ai/backend/manager/services/resource_preset/processors.py index 951efd75533..2878b4af794 100644 --- a/src/ai/backend/manager/services/resource_preset/processors.py +++ b/src/ai/backend/manager/services/resource_preset/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.resource_preset.actions.check_presets import ( CheckResourcePresetsAction, CheckResourcePresetsActionResult, @@ -34,7 +35,10 @@ class ResourcePresetProcessors(AbstractProcessorPackage): check_presets: ActionProcessor[CheckResourcePresetsAction, CheckResourcePresetsActionResult] def __init__( - self, service: ResourcePresetService, action_monitors: list[ActionMonitor] + self, + service: ResourcePresetService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_preset = ActionProcessor(service.create_preset, action_monitors) self.modify_preset = ActionProcessor(service.modify_preset, action_monitors) diff --git a/src/ai/backend/manager/services/resource_slot/processors.py b/src/ai/backend/manager/services/resource_slot/processors.py index db836645204..85ede8a604a 100644 --- a/src/ai/backend/manager/services/resource_slot/processors.py +++ b/src/ai/backend/manager/services/resource_slot/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( GetAgentResourcesAction, @@ -45,7 +46,12 @@ class ResourceSlotProcessors(AbstractProcessorPackage): GetProjectResourceOverviewAction, GetProjectResourceOverviewResult ] - def __init__(self, service: ResourceSlotService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ResourceSlotService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.get_agent_resources = ActionProcessor(service.get_agent_resources, action_monitors) self.search_agent_resources = ActionProcessor( service.search_agent_resources, action_monitors diff --git a/src/ai/backend/manager/services/resource_usage/processors.py b/src/ai/backend/manager/services/resource_usage/processors.py index 0014a15d23f..84fbcae4e4f 100644 --- a/src/ai/backend/manager/services/resource_usage/processors.py +++ b/src/ai/backend/manager/services/resource_usage/processors.py @@ -7,6 +7,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( SearchDomainUsageBucketsAction, @@ -54,7 +55,12 @@ class ResourceUsageProcessors(AbstractProcessorPackage): SearchScopedUserUsageBucketsAction, SearchScopedUserUsageBucketsActionResult ] - def __init__(self, service: ResourceUsageService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ResourceUsageService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: # Domain Usage Buckets self.search_domain_usage_buckets = ActionProcessor( service.search_domain_usage_buckets, action_monitors diff --git a/src/ai/backend/manager/services/scaling_group/processors.py b/src/ai/backend/manager/services/scaling_group/processors.py index 01a67458059..dfb7c7f0bf2 100644 --- a/src/ai/backend/manager/services/scaling_group/processors.py +++ b/src/ai/backend/manager/services/scaling_group/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.scaling_group.actions.associate_with_domain import ( AssociateScalingGroupWithDomainsAction, AssociateScalingGroupWithDomainsActionResult, @@ -97,7 +98,12 @@ class ScalingGroupProcessors(AbstractProcessorPackage): DisassociateScalingGroupWithUserGroupsActionResult, ] - def __init__(self, service: ScalingGroupService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: ScalingGroupService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_scaling_group = ActionProcessor(service.create_scaling_group, action_monitors) self.purge_scaling_group = ActionProcessor(service.purge_scaling_group, action_monitors) self.modify_scaling_group = ActionProcessor(service.modify_scaling_group, action_monitors) diff --git a/src/ai/backend/manager/services/scheduling_history/processors.py b/src/ai/backend/manager/services/scheduling_history/processors.py index e76325fde14..84cb133a677 100644 --- a/src/ai/backend/manager/services/scheduling_history/processors.py +++ b/src/ai/backend/manager/services/scheduling_history/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions import ( SearchDeploymentHistoryAction, @@ -47,7 +48,10 @@ class SchedulingHistoryProcessors(AbstractProcessorPackage): ] def __init__( - self, service: SchedulingHistoryService, action_monitors: list[ActionMonitor] + self, + service: SchedulingHistoryService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: # Admin processors self.search_session_history = ActionProcessor( diff --git a/src/ai/backend/manager/services/service_catalog/processors.py b/src/ai/backend/manager/services/service_catalog/processors.py index f975fb5f2bc..f5c2d17cefc 100644 --- a/src/ai/backend/manager/services/service_catalog/processors.py +++ b/src/ai/backend/manager/services/service_catalog/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.service_catalog.actions.search import ( SearchServiceCatalogsAction, SearchServiceCatalogsActionResult, @@ -20,7 +21,10 @@ class ServiceCatalogProcessors(AbstractProcessorPackage): ] def __init__( - self, service: ServiceCatalogService, action_monitors: list[ActionMonitor] + self, + service: ServiceCatalogService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.search_service_catalogs = ActionProcessor( service.search_service_catalogs, action_monitors diff --git a/src/ai/backend/manager/services/session/processors.py b/src/ai/backend/manager/services/session/processors.py index be32577a4f5..647568dd8ce 100644 --- a/src/ai/backend/manager/services/session/processors.py +++ b/src/ai/backend/manager/services/session/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.session.actions.check_and_transit_status import ( CheckAndTransitStatusAction, CheckAndTransitStatusActionResult, @@ -165,7 +166,12 @@ class SessionProcessors(AbstractProcessorPackage): CheckAndTransitStatusAction, CheckAndTransitStatusActionResult ] - def __init__(self, service: SessionService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: SessionService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.commit_session = ActionProcessor(service.commit_session, action_monitors) self.complete = ActionProcessor(service.complete, action_monitors) self.convert_session_to_image = ActionProcessor( diff --git a/src/ai/backend/manager/services/storage_namespace/processors.py b/src/ai/backend/manager/services/storage_namespace/processors.py index 802fcaf693d..e5b0b0d277e 100644 --- a/src/ai/backend/manager/services/storage_namespace/processors.py +++ b/src/ai/backend/manager/services/storage_namespace/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.storage_namespace.actions.get_all import ( GetAllNamespacesAction, GetAllNamespacesActionResult, @@ -36,7 +37,10 @@ class StorageNamespaceProcessors(AbstractProcessorPackage): ] def __init__( - self, service: StorageNamespaceService, action_monitors: list[ActionMonitor] + self, + service: StorageNamespaceService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.register = ActionProcessor(service.register, action_monitors) self.unregister = ActionProcessor(service.unregister, action_monitors) diff --git a/src/ai/backend/manager/services/template/processors.py b/src/ai/backend/manager/services/template/processors.py index 584cc7af651..c32b11fb62a 100644 --- a/src/ai/backend/manager/services/template/processors.py +++ b/src/ai/backend/manager/services/template/processors.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from .actions.create_cluster_template import ( CreateClusterTemplateAction, @@ -66,7 +67,12 @@ class TemplateProcessors(AbstractProcessorPackage): update_cluster: ActionProcessor[UpdateClusterTemplateAction, UpdateClusterTemplateActionResult] delete_cluster: ActionProcessor[DeleteClusterTemplateAction, DeleteClusterTemplateActionResult] - def __init__(self, service: TemplateService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: TemplateService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_task = ActionProcessor(service.create_task_template, action_monitors) self.list_task = ActionProcessor(service.list_task_templates, action_monitors) self.get_task = ActionProcessor(service.get_task_template, action_monitors) diff --git a/src/ai/backend/manager/services/user/processors.py b/src/ai/backend/manager/services/user/processors.py index 2b510ca0db6..4d8e159561b 100644 --- a/src/ai/backend/manager/services/user/processors.py +++ b/src/ai/backend/manager/services/user/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.user.actions.admin_month_stats import ( AdminMonthStatsAction, AdminMonthStatsActionResult, @@ -76,7 +77,12 @@ class UserProcessors(AbstractProcessorPackage): ] search_users_by_role: ActionProcessor[SearchUsersByRoleAction, SearchUsersByRoleActionResult] - def __init__(self, user_service: UserService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + user_service: UserService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_user = ActionProcessor(user_service.create_user, action_monitors) self.bulk_create_users = ActionProcessor(user_service.bulk_create_users, action_monitors) self.modify_user = ActionProcessor(user_service.modify_user, action_monitors) diff --git a/src/ai/backend/manager/services/user_resource_policy/processors.py b/src/ai/backend/manager/services/user_resource_policy/processors.py index 5d70f739a9e..4505b1aa702 100644 --- a/src/ai/backend/manager/services/user_resource_policy/processors.py +++ b/src/ai/backend/manager/services/user_resource_policy/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.user_resource_policy.actions.create_user_resource_policy import ( CreateUserResourcePolicyAction, CreateUserResourcePolicyActionResult, @@ -30,7 +31,10 @@ class UserResourcePolicyProcessors(AbstractProcessorPackage): ] def __init__( - self, service: UserResourcePolicyService, action_monitors: list[ActionMonitor] + self, + service: UserResourcePolicyService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.create_user_resource_policy = ActionProcessor( service.create_user_resource_policy, action_monitors diff --git a/src/ai/backend/manager/services/vfolder/processors/file.py b/src/ai/backend/manager/services/vfolder/processors/file.py index bb8f23ff075..2c0714a7f1f 100644 --- a/src/ai/backend/manager/services/vfolder/processors/file.py +++ b/src/ai/backend/manager/services/vfolder/processors/file.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.vfolder.actions.file import ( CreateArchiveDownloadSessionAction, CreateArchiveDownloadSessionActionResult, @@ -39,7 +40,12 @@ class VFolderFileProcessors(AbstractProcessorPackage): mkdir: ActionProcessor[MkdirAction, MkdirActionResult] move_file: ActionProcessor[MoveFileAction, MoveFileActionResult] - def __init__(self, service: VFolderFileService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: VFolderFileService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.upload_file = ActionProcessor(service.upload_file, action_monitors) self.download_file = ActionProcessor(service.download_file, action_monitors) self.create_archive_download_session = ActionProcessor( diff --git a/src/ai/backend/manager/services/vfolder/processors/invite.py b/src/ai/backend/manager/services/vfolder/processors/invite.py index 793cb5b7125..ba6751eadd2 100644 --- a/src/ai/backend/manager/services/vfolder/processors/invite.py +++ b/src/ai/backend/manager/services/vfolder/processors/invite.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.vfolder.actions.invite import ( AcceptInvitationAction, AcceptInvitationActionResult, @@ -45,7 +46,12 @@ class VFolderInviteProcessors(AbstractProcessorPackage): ListSentInvitationsAction, ListSentInvitationsActionResult ] - def __init__(self, service: VFolderInviteService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: VFolderInviteService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.invite_vfolder = ActionProcessor(service.invite, action_monitors) self.accept_invitation = ActionProcessor(service.accept_invitation, action_monitors) self.reject_invitation = ActionProcessor(service.reject_invitation, action_monitors) diff --git a/src/ai/backend/manager/services/vfolder/processors/sharing.py b/src/ai/backend/manager/services/vfolder/processors/sharing.py index dfe24f52bcf..f3459b7cfcc 100644 --- a/src/ai/backend/manager/services/vfolder/processors/sharing.py +++ b/src/ai/backend/manager/services/vfolder/processors/sharing.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.vfolder.actions.sharing import ( ListSharedVFoldersAction, ListSharedVFoldersActionResult, @@ -25,7 +26,10 @@ class VFolderSharingProcessors(AbstractProcessorPackage): ] def __init__( - self, service: VFolderSharingService, action_monitors: list[ActionMonitor] + self, + service: VFolderSharingService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, ) -> None: self.share = ActionProcessor(service.share, action_monitors) self.unshare = ActionProcessor(service.unshare, action_monitors) diff --git a/src/ai/backend/manager/services/vfolder/processors/vfolder.py b/src/ai/backend/manager/services/vfolder/processors/vfolder.py index a3ea3050434..7079b07308c 100644 --- a/src/ai/backend/manager/services/vfolder/processors/vfolder.py +++ b/src/ai/backend/manager/services/vfolder/processors/vfolder.py @@ -5,6 +5,7 @@ from ai.backend.manager.actions.processor.scope import ScopeActionProcessor from ai.backend.manager.actions.processor.single_entity import SingleEntityActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.services.vfolder.actions.base import ( CloneVFolderAction, CloneVFolderActionResult, @@ -105,7 +106,12 @@ class VFolderProcessors(AbstractProcessorPackage): GetAccessibleVFolderAction, GetAccessibleVFolderActionResult ] - def __init__(self, service: VFolderService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: VFolderService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self.create_vfolder = ScopeActionProcessor(service.create, action_monitors) self.get_vfolder = SingleEntityActionProcessor(service.get, action_monitors) self.list_vfolder = ScopeActionProcessor(service.list, action_monitors) diff --git a/src/ai/backend/manager/services/vfs_storage/processors.py b/src/ai/backend/manager/services/vfs_storage/processors.py index 65c54e2ce44..6a2e677f180 100644 --- a/src/ai/backend/manager/services/vfs_storage/processors.py +++ b/src/ai/backend/manager/services/vfs_storage/processors.py @@ -3,6 +3,7 @@ from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.processor import ActionProcessor from ai.backend.manager.actions.types import AbstractProcessorPackage, ActionSpec +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.manager_facing_client import ( StorageProxyManagerFacingClient, ) @@ -61,7 +62,12 @@ class VFSStorageProcessors(AbstractProcessorPackage): set_quota_scope: ActionProcessor[SetQuotaScopeAction, SetQuotaScopeActionResult] unset_quota_scope: ActionProcessor[UnsetQuotaScopeAction, UnsetQuotaScopeActionResult] - def __init__(self, service: VFSStorageService, action_monitors: list[ActionMonitor]) -> None: + def __init__( + self, + service: VFSStorageService, + action_monitors: list[ActionMonitor], + validators: ActionValidators, + ) -> None: self._service = service self.create = ActionProcessor(service.create, action_monitors) self.update = ActionProcessor(service.update, action_monitors) diff --git a/tests/component/agent_api/conftest.py b/tests/component/agent_api/conftest.py index 1f98e364137..c0302b9565f 100644 --- a/tests/component/agent_api/conftest.py +++ b/tests/component/agent_api/conftest.py @@ -3,6 +3,7 @@ import secrets from collections.abc import AsyncIterator from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa @@ -12,6 +13,7 @@ from ai.backend.common.events.dispatcher import EventProducer from ai.backend.common.plugin.hook import HookPluginContext from ai.backend.common.types import HostPortPair, ResourceSlot +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.agent_cache import AgentRPCCache from ai.backend.manager.api.rest.agent.handler import AgentHandler from ai.backend.manager.api.rest.agent.registry import register_agent_routes @@ -84,7 +86,9 @@ def agent_processors( event_producer=event_producer, agent_cache=agent_cache, ) - return AgentProcessors(service=service, action_monitors=[]) + return AgentProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/artifact/conftest.py b/tests/component/artifact/conftest.py index b77a8d972ea..2296c576a12 100644 --- a/tests/component/artifact/conftest.py +++ b/tests/component/artifact/conftest.py @@ -4,12 +4,14 @@ from collections.abc import AsyncIterator, Callable, Coroutine from dataclasses import dataclass from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine from ai.backend.common.bgtask.bgtask import BackgroundTaskManager +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.artifact.handler import ArtifactHandler from ai.backend.manager.api.rest.artifact.registry import register_artifact_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -73,7 +75,9 @@ def artifact_processors( storage_manager=storage_manager, config_provider=config_provider, ) - return ArtifactProcessors(service=service, action_monitors=[]) + return ArtifactProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -106,7 +110,9 @@ def artifact_revision_processors( valkey_artifact_client=valkey_clients.artifact, background_task_manager=background_task_manager, ) - return ArtifactRevisionProcessors(service=service, action_monitors=[]) + return ArtifactRevisionProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/artifact_registry/conftest.py b/tests/component/artifact_registry/conftest.py index 3a2e61dc663..ed56fce97c8 100644 --- a/tests/component/artifact_registry/conftest.py +++ b/tests/component/artifact_registry/conftest.py @@ -4,6 +4,7 @@ from collections.abc import AsyncIterator, Callable, Coroutine from dataclasses import dataclass from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa @@ -11,6 +12,7 @@ from ai.backend.common.bgtask.bgtask import BackgroundTaskManager from ai.backend.common.data.artifact.types import ArtifactRegistryType +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.artifact_registry.handler import ArtifactRegistryHandler from ai.backend.manager.api.rest.artifact_registry.registry import ( register_artifact_registry_routes, @@ -82,7 +84,9 @@ def artifact_processors( storage_manager=storage_manager, config_provider=config_provider, ) - return ArtifactProcessors(service=service, action_monitors=[]) + return ArtifactProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -115,7 +119,9 @@ def artifact_revision_processors( valkey_artifact_client=valkey_clients.artifact, background_task_manager=background_task_manager, ) - return ArtifactRevisionProcessors(service=service, action_monitors=[]) + return ArtifactRevisionProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/artifact_revision/conftest.py b/tests/component/artifact_revision/conftest.py index b5c2a19b0f1..c05d2bb6e1c 100644 --- a/tests/component/artifact_revision/conftest.py +++ b/tests/component/artifact_revision/conftest.py @@ -4,6 +4,7 @@ from collections.abc import AsyncIterator, Callable, Coroutine from dataclasses import dataclass from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa @@ -11,6 +12,7 @@ from ai.backend.common.bgtask.bgtask import BackgroundTaskManager from ai.backend.common.data.artifact.types import ArtifactRegistryType +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.artifact.handler import ArtifactHandler from ai.backend.manager.api.rest.artifact.registry import register_artifact_routes from ai.backend.manager.api.rest.artifact_registry.handler import ArtifactRegistryHandler @@ -80,7 +82,9 @@ def artifact_processors( storage_manager=storage_manager, config_provider=config_provider, ) - return ArtifactProcessors(service=service, action_monitors=[]) + return ArtifactProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -113,7 +117,9 @@ def artifact_revision_processors( valkey_artifact_client=valkey_clients.artifact, background_task_manager=background_task_manager, ) - return ArtifactRevisionProcessors(service=service, action_monitors=[]) + return ArtifactRevisionProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/auto_scaling_rule/conftest.py b/tests/component/auto_scaling_rule/conftest.py index 35a2425af19..c1c81b5e886 100644 --- a/tests/component/auto_scaling_rule/conftest.py +++ b/tests/component/auto_scaling_rule/conftest.py @@ -12,6 +12,7 @@ from ai.backend.common.container_registry import ContainerRegistryType from ai.backend.common.data.endpoint.types import EndpointLifecycle from ai.backend.common.types import ResourceSlot +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.admin.handler import AdminHandler from ai.backend.manager.api.rest.admin.registry import register_admin_routes from ai.backend.manager.api.rest.auto_scaling_rule.handler import AutoScalingRuleHandler @@ -59,7 +60,9 @@ def deployment_processors( deployment_controller = AsyncMock() revision_generator_registry = MagicMock() service = DeploymentService(deployment_controller, repo, revision_generator_registry) - return DeploymentProcessors(service=service, action_monitors=[]) + return DeploymentProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/config/conftest.py b/tests/component/config/conftest.py index e302728e60e..4e1a94fce4d 100644 --- a/tests/component/config/conftest.py +++ b/tests/component/config/conftest.py @@ -4,6 +4,7 @@ import uuid from collections.abc import AsyncIterator, Callable, Coroutine from typing import Any +from unittest.mock import MagicMock import pytest from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine @@ -18,6 +19,7 @@ DeleteGroupDotfileRequest, DeleteUserDotfileRequest, ) +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.domainconfig.handler import DomainConfigHandler from ai.backend.manager.api.rest.domainconfig.registry import register_domainconfig_routes from ai.backend.manager.api.rest.groupconfig.handler import GroupConfigHandler @@ -41,7 +43,9 @@ def dotfile_processors(database_engine: ExtendedAsyncSAEngine) -> DotfileProcessors: repo = DotfileRepository(database_engine) service = DotfileService(repo) - return DotfileProcessors(service=service, action_monitors=[]) + return DotfileProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/conftest.py b/tests/component/conftest.py index c5ed3d075e7..c0da4c1d233 100644 --- a/tests/component/conftest.py +++ b/tests/component/conftest.py @@ -73,6 +73,7 @@ from ai.backend.logging import LocalLogger, LogLevel from ai.backend.logging.config import ConsoleConfig, LogDriver, LoggingConfig from ai.backend.logging.types import LogFormat +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.agent_cache import AgentRPCCache from ai.backend.manager.api import ManagerStatus from ai.backend.manager.api.rest.app import build_root_app, mount_registries @@ -1184,7 +1185,9 @@ def auth_processors( auth_repository=repo, config_provider=config_provider, ) - return AuthProcessors(service=service, action_monitors=[]) + return AuthProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) # --------------------------------------------------------------------------- diff --git a/tests/component/container_registry/conftest.py b/tests/component/container_registry/conftest.py index 60a7f62d891..c4b6b2c22a6 100644 --- a/tests/component/container_registry/conftest.py +++ b/tests/component/container_registry/conftest.py @@ -2,12 +2,14 @@ import uuid from collections.abc import AsyncIterator +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine from ai.backend.common.container_registry import ContainerRegistryType +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.container_registry.handler import ContainerRegistryHandler from ai.backend.manager.api.rest.container_registry.registry import ( register_container_registry_routes, @@ -29,7 +31,9 @@ def container_registry_processors( ) -> ContainerRegistryProcessors: repo = ContainerRegistryRepository(database_engine) service = ContainerRegistryService(database_engine, repo) - return ContainerRegistryProcessors(service=service, action_monitors=[]) + return ContainerRegistryProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/deployment/conftest.py b/tests/component/deployment/conftest.py index 9a7d182ec31..09d9d17e7e6 100644 --- a/tests/component/deployment/conftest.py +++ b/tests/component/deployment/conftest.py @@ -4,6 +4,7 @@ import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.deployment.handler import DeploymentAPIHandler from ai.backend.manager.api.rest.deployment.registry import register_deployment_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -32,7 +33,9 @@ def deployment_processors( deployment_controller = AsyncMock() revision_generator_registry = MagicMock() service = DeploymentService(deployment_controller, repo, revision_generator_registry) - return DeploymentProcessors(service=service, action_monitors=[]) + return DeploymentProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/domain/conftest.py b/tests/component/domain/conftest.py index 3e011907943..64282c8222d 100644 --- a/tests/component/domain/conftest.py +++ b/tests/component/domain/conftest.py @@ -15,6 +15,7 @@ CreateDomainResponse, PurgeDomainRequest, ) +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.admin.handler import AdminHandler from ai.backend.manager.api.rest.admin.registry import register_admin_routes from ai.backend.manager.api.rest.domain.handler import DomainHandler @@ -35,7 +36,9 @@ def domain_processors(database_engine: ExtendedAsyncSAEngine) -> DomainProcessors: repo = DomainRepository(database_engine) service = DomainService(repo) - return DomainProcessors(service=service, action_monitors=[]) + return DomainProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/error_log/conftest.py b/tests/component/error_log/conftest.py index 226742b40e8..a0fd97093f4 100644 --- a/tests/component/error_log/conftest.py +++ b/tests/component/error_log/conftest.py @@ -2,11 +2,13 @@ from collections.abc import AsyncIterator from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.error_log.handler import ErrorLogHandler from ai.backend.manager.api.rest.error_log.registry import register_error_log_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -22,7 +24,9 @@ def error_log_processors(database_engine: ExtendedAsyncSAEngine) -> ErrorLogProcessors: repo = ErrorLogRepository(database_engine) service = ErrorLogService(repo) - return ErrorLogProcessors(service=service, action_monitors=[]) + return ErrorLogProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/etcd_config/conftest.py b/tests/component/etcd_config/conftest.py index d48059eaf03..f524f64204c 100644 --- a/tests/component/etcd_config/conftest.py +++ b/tests/component/etcd_config/conftest.py @@ -1,8 +1,11 @@ from __future__ import annotations +from unittest.mock import MagicMock + import pytest from ai.backend.common.etcd import AsyncEtcd +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.etcd.handler import EtcdHandler from ai.backend.manager.api.rest.etcd.registry import register_etcd_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -26,7 +29,9 @@ def container_registry_processors( ) -> ContainerRegistryProcessors: repo = ContainerRegistryRepository(database_engine) service = ContainerRegistryService(database_engine, repo) - return ContainerRegistryProcessors(service=service, action_monitors=[]) + return ContainerRegistryProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -43,7 +48,9 @@ def etcd_config_processors( etcd=async_etcd, valkey_stat=valkey_clients.stat, ) - return EtcdConfigProcessors(service=service, action_monitors=[]) + return EtcdConfigProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/export/conftest.py b/tests/component/export/conftest.py index 8b372115289..cfed059ac06 100644 --- a/tests/component/export/conftest.py +++ b/tests/component/export/conftest.py @@ -4,6 +4,7 @@ import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.export.handler import ExportHandler from ai.backend.manager.api.rest.export.registry import register_export_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -22,7 +23,9 @@ def export_processors(database_engine: ExtendedAsyncSAEngine) -> ExportProcessor registry = ExportReportRegistry.create_default() repo = ExportRepository(db_source, registry) service = ExportService(repo) - return ExportProcessors(service=service, action_monitors=[]) + return ExportProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/fair_share/conftest.py b/tests/component/fair_share/conftest.py index 52aa24b52cf..8d307a795e4 100644 --- a/tests/component/fair_share/conftest.py +++ b/tests/component/fair_share/conftest.py @@ -3,11 +3,13 @@ import secrets import uuid from collections.abc import AsyncIterator +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.fair_share.handler import FairShareAPIHandler from ai.backend.manager.api.rest.fair_share.registry import register_fair_share_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -32,21 +34,27 @@ def fair_share_processors(database_engine: ExtendedAsyncSAEngine) -> FairShareProcessors: repo = FairShareRepository(database_engine) service = FairShareService(repo) - return FairShareProcessors(service=service, action_monitors=[]) + return FairShareProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() def resource_usage_processors(database_engine: ExtendedAsyncSAEngine) -> ResourceUsageProcessors: repo = ResourceUsageHistoryRepository(database_engine) service = ResourceUsageService(repo) - return ResourceUsageProcessors(service=service, action_monitors=[]) + return ResourceUsageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() def scaling_group_processors(database_engine: ExtendedAsyncSAEngine) -> ScalingGroupProcessors: repo = ScalingGroupRepository(database_engine) service = ScalingGroupService(repo, appproxy_client_pool=None) - return ScalingGroupProcessors(service=service, action_monitors=[]) + return ScalingGroupProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/group/conftest.py b/tests/component/group/conftest.py index 4cace3b6dd1..678d7518131 100644 --- a/tests/component/group/conftest.py +++ b/tests/component/group/conftest.py @@ -4,11 +4,13 @@ import uuid from collections.abc import AsyncIterator from typing import cast +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.group.handler import GroupHandler from ai.backend.manager.api.rest.group.registry import register_group_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -58,7 +60,9 @@ def container_registry_processors( repo = ContainerRegistryRepository(database_engine) quota_service = cast(AbstractPerProjectContainerRegistryQuotaService, InMemoryQuotaService()) service = ContainerRegistryService(database_engine, repo, quota_service=quota_service) - return ContainerRegistryProcessors(service=service, action_monitors=[]) + return ContainerRegistryProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/image/conftest.py b/tests/component/image/conftest.py index 35fdc4582e5..45516030d68 100644 --- a/tests/component/image/conftest.py +++ b/tests/component/image/conftest.py @@ -9,6 +9,7 @@ from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine from ai.backend.common.container_registry import ContainerRegistryType +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.admin.handler import AdminHandler from ai.backend.manager.api.rest.admin.registry import register_admin_routes from ai.backend.manager.api.rest.image.handler import ImageHandler @@ -36,7 +37,9 @@ def image_processors( ) -> ImageProcessors: repo = ImageRepository(database_engine, valkey_clients.image, config_provider) service = ImageService(agent_registry, repo, config_provider) - return ImageProcessors(service=service, action_monitors=[]) + return ImageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/infra/conftest.py b/tests/component/infra/conftest.py index 9457b17da81..2f6b00a03eb 100644 --- a/tests/component/infra/conftest.py +++ b/tests/component/infra/conftest.py @@ -2,7 +2,7 @@ import uuid from collections.abc import AsyncIterator -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, MagicMock import pytest import sqlalchemy as sa @@ -12,6 +12,7 @@ from ai.backend.common.events.dispatcher import EventProducer from ai.backend.common.plugin.hook import HookPluginContext from ai.backend.common.types import ResourceSlot +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.etcd.handler import EtcdHandler from ai.backend.manager.api.rest.etcd.registry import register_etcd_routes from ai.backend.manager.api.rest.resource.handler import ResourceHandler @@ -58,7 +59,9 @@ def container_registry_processors( ) -> ContainerRegistryProcessors: repo = ContainerRegistryRepository(database_engine) service = ContainerRegistryService(database_engine, repo) - return ContainerRegistryProcessors(service=service, action_monitors=[]) + return ContainerRegistryProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -75,7 +78,9 @@ def etcd_config_processors( etcd=async_etcd, valkey_stat=valkey_clients.stat, ) - return EtcdConfigProcessors(service=service, action_monitors=[]) + return EtcdConfigProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -86,7 +91,9 @@ def resource_preset_processors( ) -> ResourcePresetProcessors: repo = ResourcePresetRepository(database_engine, valkey_clients.stat, config_provider) service = ResourcePresetService(repo) - return ResourcePresetProcessors(service=service, action_monitors=[]) + return ResourcePresetProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -116,7 +123,9 @@ def agent_processors( event_producer=event_producer, agent_cache=AsyncMock(), ) - return AgentProcessors(service=service, action_monitors=[]) + return AgentProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -131,7 +140,9 @@ def group_processors( ) group_repos = GroupRepositories(repository=group_repo) service = GroupService(storage_manager, config_provider, valkey_clients.stat, group_repos) - return GroupProcessors(group_service=service, action_monitors=[]) + return GroupProcessors( + group_service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -142,7 +153,9 @@ def user_processors( ) -> UserProcessors: user_repo = UserRepository(database_engine) service = UserService(storage_manager, valkey_clients.stat, AsyncMock(), user_repo) - return UserProcessors(user_service=service, action_monitors=[]) + return UserProcessors( + user_service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -151,7 +164,9 @@ def scaling_group_processors( ) -> ScalingGroupProcessors: repo = ScalingGroupRepository(database_engine) service = ScalingGroupService(repo, appproxy_client_pool=AsyncMock()) - return ScalingGroupProcessors(service=service, action_monitors=[]) + return ScalingGroupProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/model_serving/conftest.py b/tests/component/model_serving/conftest.py index f179c103165..f1b54ad93cd 100644 --- a/tests/component/model_serving/conftest.py +++ b/tests/component/model_serving/conftest.py @@ -1,11 +1,12 @@ from __future__ import annotations -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, MagicMock import pytest from ai.backend.common.bgtask.bgtask import BackgroundTaskManager from ai.backend.common.events.hub.hub import EventHub +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.routing import RouteRegistry from ai.backend.manager.api.rest.service.handler import ServiceHandler from ai.backend.manager.api.rest.service.registry import register_service_routes @@ -66,7 +67,9 @@ def model_serving_processors( scheduling_controller=AsyncMock(), revision_generator_registry=revision_gen, ) - return ModelServingProcessors(service=service, action_monitors=[]) + return ModelServingProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -76,7 +79,9 @@ def auto_scaling_processors( """Real ModelServingAutoScalingProcessors with real AutoScalingService.""" repo = ModelServingRepository(database_engine) service = AutoScalingService(repository=repo) - return ModelServingAutoScalingProcessors(service=service, action_monitors=[]) + return ModelServingAutoScalingProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -98,7 +103,9 @@ def deployment_processors( RevisionGeneratorRegistryArgs(deployment_repository=repo) ) service = DeploymentService(deployment_controller, repo, revision_generator_registry) - return DeploymentProcessors(service=service, action_monitors=[]) + return DeploymentProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/notification/conftest.py b/tests/component/notification/conftest.py index 75d8d8b7413..dddcdff0bda 100644 --- a/tests/component/notification/conftest.py +++ b/tests/component/notification/conftest.py @@ -1,7 +1,10 @@ from __future__ import annotations +from unittest.mock import MagicMock + import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.notification.handler import NotificationHandler from ai.backend.manager.api.rest.notification.registry import register_notification_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -20,7 +23,9 @@ def notification_processors( ) -> NotificationProcessors: repo = NotificationRepository(database_engine) service = NotificationService(repo, notification_center) - return NotificationProcessors(service=service, action_monitors=[]) + return NotificationProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/object_storage/conftest.py b/tests/component/object_storage/conftest.py index 9d30f3a2eda..21ecc86b670 100644 --- a/tests/component/object_storage/conftest.py +++ b/tests/component/object_storage/conftest.py @@ -4,11 +4,13 @@ import uuid from collections.abc import AsyncIterator, Callable, Coroutine from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.middleware import auth as _auth_api from ai.backend.manager.api.rest.object_storage.handler import ObjectStorageHandler from ai.backend.manager.api.rest.object_storage.registry import register_object_storage_routes @@ -54,7 +56,9 @@ def object_storage_processors( storage_manager=storage_manager, config_provider=config_provider, ) - return ObjectStorageProcessors(service=service, action_monitors=[]) + return ObjectStorageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -65,7 +69,9 @@ def storage_namespace_processors( service = StorageNamespaceService( storage_namespace_repository=storage_namespace_repository, ) - return StorageNamespaceProcessors(service=service, action_monitors=[]) + return StorageNamespaceProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/operations/conftest.py b/tests/component/operations/conftest.py index a156ed5bc5c..fe38cda72ca 100644 --- a/tests/component/operations/conftest.py +++ b/tests/component/operations/conftest.py @@ -3,6 +3,7 @@ import secrets from collections.abc import AsyncIterator from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa @@ -10,6 +11,7 @@ from ai.backend.common.etcd import AsyncEtcd, ConfigScopes from ai.backend.common.types import HostPortPair, ResourceSlot +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.error_log.handler import ErrorLogHandler from ai.backend.manager.api.rest.error_log.registry import register_error_log_routes from ai.backend.manager.api.rest.manager.handler import ManagerHandler @@ -34,7 +36,9 @@ def error_log_processors(database_engine: ExtendedAsyncSAEngine) -> ErrorLogProcessors: repo = ErrorLogRepository(database_engine) service = ErrorLogService(repo) - return ErrorLogProcessors(service=service, action_monitors=[]) + return ErrorLogProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -69,7 +73,9 @@ def manager_admin_processors( db=database_engine, valkey_stat=valkey_clients.stat, ) - return ManagerAdminProcessors(service=service, action_monitors=[]) + return ManagerAdminProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/quota_scope/conftest.py b/tests/component/quota_scope/conftest.py index 940eedbe4f3..cbdddd15586 100644 --- a/tests/component/quota_scope/conftest.py +++ b/tests/component/quota_scope/conftest.py @@ -4,6 +4,7 @@ import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.admin.handler import AdminHandler from ai.backend.manager.api.rest.admin.registry import register_admin_routes from ai.backend.manager.api.rest.quota_scope.handler import QuotaScopeHandler @@ -23,7 +24,9 @@ def vfs_storage_processors( ) -> VFSStorageProcessors: repo = VFSStorageRepository(database_engine) service = VFSStorageService(repo, storage_manager=storage_manager) - return VFSStorageProcessors(service=service, action_monitors=[]) + return VFSStorageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/rbac/conftest.py b/tests/component/rbac/conftest.py index f067325759a..99383fe2612 100644 --- a/tests/component/rbac/conftest.py +++ b/tests/component/rbac/conftest.py @@ -15,6 +15,7 @@ ) from ai.backend.common.dto.manager.rbac.response import CreateRoleResponse from ai.backend.common.dto.manager.rbac.types import RoleSource, RoleStatus +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.admin.handler import AdminHandler from ai.backend.manager.api.rest.admin.registry import register_admin_routes from ai.backend.manager.api.rest.rbac.handler import RBACHandler @@ -39,7 +40,9 @@ def permission_controller_processors( ) -> PermissionControllerProcessors: repo = PermissionControllerRepository(database_engine) service = PermissionControllerService(repo) - return PermissionControllerProcessors(service=service, action_monitors=[]) + return PermissionControllerProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/resource_preset/conftest.py b/tests/component/resource_preset/conftest.py index db795234821..4b942ec263d 100644 --- a/tests/component/resource_preset/conftest.py +++ b/tests/component/resource_preset/conftest.py @@ -3,7 +3,7 @@ import uuid from collections.abc import AsyncIterator, Callable, Coroutine from typing import Any -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, MagicMock import pytest import sqlalchemy as sa @@ -13,6 +13,7 @@ from ai.backend.common.events.dispatcher import EventProducer from ai.backend.common.plugin.hook import HookPluginContext from ai.backend.common.types import ResourceSlot +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.middleware import auth as _auth_api from ai.backend.manager.api.rest.resource.handler import ResourceHandler from ai.backend.manager.api.rest.resource.registry import register_resource_routes @@ -56,7 +57,9 @@ def container_registry_processors( ) -> ContainerRegistryProcessors: repo = ContainerRegistryRepository(database_engine) service = ContainerRegistryService(database_engine, repo) - return ContainerRegistryProcessors(service=service, action_monitors=[]) + return ContainerRegistryProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -67,7 +70,9 @@ def resource_preset_processors( ) -> ResourcePresetProcessors: repo = ResourcePresetRepository(database_engine, valkey_clients.stat, config_provider) service = ResourcePresetService(repo) - return ResourcePresetProcessors(service=service, action_monitors=[]) + return ResourcePresetProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -97,7 +102,9 @@ def agent_processors( event_producer=event_producer, agent_cache=AsyncMock(), ) - return AgentProcessors(service=service, action_monitors=[]) + return AgentProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -112,7 +119,9 @@ def group_processors( ) group_repos = GroupRepositories(repository=group_repo) service = GroupService(storage_manager, config_provider, valkey_clients.stat, group_repos) - return GroupProcessors(group_service=service, action_monitors=[]) + return GroupProcessors( + group_service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -123,7 +132,9 @@ def user_processors( ) -> UserProcessors: user_repo = UserRepository(database_engine) service = UserService(storage_manager, valkey_clients.stat, AsyncMock(), user_repo) - return UserProcessors(user_service=service, action_monitors=[]) + return UserProcessors( + user_service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/scaling_group/conftest.py b/tests/component/scaling_group/conftest.py index 5ebb7d9a197..7a5496cb467 100644 --- a/tests/component/scaling_group/conftest.py +++ b/tests/component/scaling_group/conftest.py @@ -1,7 +1,10 @@ from __future__ import annotations +from unittest.mock import MagicMock + import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.routing import RouteRegistry from ai.backend.manager.api.rest.scaling_group.handler import ScalingGroupHandler from ai.backend.manager.api.rest.scaling_group.registry import register_scaling_group_routes @@ -16,7 +19,9 @@ def scaling_group_processors(database_engine: ExtendedAsyncSAEngine) -> ScalingGroupProcessors: repo = ScalingGroupRepository(database_engine) service = ScalingGroupService(repo) - return ScalingGroupProcessors(service=service, action_monitors=[]) + return ScalingGroupProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/scheduling_history/conftest.py b/tests/component/scheduling_history/conftest.py index 9a8e595a3e3..e01f5aeead2 100644 --- a/tests/component/scheduling_history/conftest.py +++ b/tests/component/scheduling_history/conftest.py @@ -1,7 +1,10 @@ from __future__ import annotations +from unittest.mock import MagicMock + import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.routing import RouteRegistry # Statically imported so that Pants includes these modules in the test PEX. @@ -26,7 +29,9 @@ def scheduling_history_processors( ) -> SchedulingHistoryProcessors: repo = SchedulingHistoryRepository(database_engine) service = SchedulingHistoryService(repo) - return SchedulingHistoryProcessors(service=service, action_monitors=[]) + return SchedulingHistoryProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/session/conftest.py b/tests/component/session/conftest.py index 8fb8544b4a5..e355913475c 100644 --- a/tests/component/session/conftest.py +++ b/tests/component/session/conftest.py @@ -6,7 +6,7 @@ from dataclasses import dataclass from datetime import datetime from typing import Any -from unittest.mock import AsyncMock +from unittest.mock import AsyncMock, MagicMock import pytest import sqlalchemy as sa @@ -16,6 +16,7 @@ from ai.backend.common.bgtask.bgtask import BackgroundTaskManager from ai.backend.common.plugin.monitor import ErrorPluginContext from ai.backend.common.types import ResourceSlot, SessionId, SessionTypes +from ai.backend.manager.actions.validators import ActionValidators # Statically imported so that Pants includes these modules in the test PEX. # build_root_app() loads them at runtime via importlib.import_module(), @@ -81,19 +82,25 @@ async def session_processors( appproxy_client_pool=appproxy_client_pool, ) service = SessionService(args) - return SessionProcessors(service=service, action_monitors=[]) + return SessionProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() def agent_processors_mock() -> AgentProcessors: """AgentProcessors with a mocked AgentService.""" - return AgentProcessors(service=AsyncMock(), action_monitors=[]) + return AgentProcessors( + service=AsyncMock(), action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() def vfolder_processors_mock() -> VFolderProcessors: """VFolderProcessors with a mocked VFolderService.""" - return VFolderProcessors(service=AsyncMock(), action_monitors=[]) + return VFolderProcessors( + service=AsyncMock(), action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/storage/conftest.py b/tests/component/storage/conftest.py index 00dd556bd33..84c72d4d6f7 100644 --- a/tests/component/storage/conftest.py +++ b/tests/component/storage/conftest.py @@ -1,7 +1,10 @@ from __future__ import annotations +from unittest.mock import MagicMock + import pytest +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.middleware import auth as _auth_api from ai.backend.manager.api.rest.object_storage.handler import ObjectStorageHandler from ai.backend.manager.api.rest.object_storage.registry import register_object_storage_routes @@ -45,7 +48,9 @@ def object_storage_processors( storage_manager=storage_manager, config_provider=config_provider, ) - return ObjectStorageProcessors(service=service, action_monitors=[]) + return ObjectStorageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -56,7 +61,9 @@ def storage_namespace_processors( service = StorageNamespaceService( storage_namespace_repository=storage_namespace_repository, ) - return StorageNamespaceProcessors(service=service, action_monitors=[]) + return StorageNamespaceProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -69,7 +76,9 @@ def vfs_storage_processors( vfs_storage_repository=vfs_storage_repository, storage_manager=storage_manager, ) - return VFSStorageProcessors(service=service, action_monitors=[]) + return VFSStorageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/storage_namespace/conftest.py b/tests/component/storage_namespace/conftest.py index eca54b354fd..a15b91a6a72 100644 --- a/tests/component/storage_namespace/conftest.py +++ b/tests/component/storage_namespace/conftest.py @@ -4,11 +4,13 @@ import uuid from collections.abc import AsyncIterator, Callable, Coroutine from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.middleware import auth as _auth_api from ai.backend.manager.api.rest.object_storage.handler import ObjectStorageHandler from ai.backend.manager.api.rest.object_storage.registry import register_object_storage_routes @@ -51,7 +53,9 @@ def object_storage_processors( storage_manager=storage_manager, config_provider=config_provider, ) - return ObjectStorageProcessors(service=service, action_monitors=[]) + return ObjectStorageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -62,7 +66,9 @@ def storage_namespace_processors( service = StorageNamespaceService( storage_namespace_repository=storage_namespace_repository, ) - return StorageNamespaceProcessors(service=service, action_monitors=[]) + return StorageNamespaceProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/template/conftest.py b/tests/component/template/conftest.py index a38733ee097..1a0199512a8 100644 --- a/tests/component/template/conftest.py +++ b/tests/component/template/conftest.py @@ -1,11 +1,13 @@ from __future__ import annotations import uuid +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.cluster_template.handler import ClusterTemplateHandler from ai.backend.manager.api.rest.cluster_template.registry import register_cluster_template_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -24,7 +26,9 @@ def template_processors(database_engine: ExtendedAsyncSAEngine) -> TemplateProcessors: repo = TemplateRepository(database_engine) service = TemplateService(repository=repo) - return TemplateProcessors(service=service, action_monitors=[]) + return TemplateProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/user/conftest.py b/tests/component/user/conftest.py index 8b170400853..533b27cb333 100644 --- a/tests/component/user/conftest.py +++ b/tests/component/user/conftest.py @@ -16,6 +16,7 @@ PurgeUserRequest, UserStatus, ) +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.admin.handler import AdminHandler from ai.backend.manager.api.rest.admin.registry import register_admin_routes from ai.backend.manager.api.rest.routing import RouteRegistry @@ -50,7 +51,9 @@ def user_processors( agent_registry=agent_registry, user_repository=user_repository, ) - return UserProcessors(user_service=service, action_monitors=[]) + return UserProcessors( + user_service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/vfolder/conftest.py b/tests/component/vfolder/conftest.py index 4c556073062..2ecb49d8e8a 100644 --- a/tests/component/vfolder/conftest.py +++ b/tests/component/vfolder/conftest.py @@ -4,6 +4,7 @@ import uuid from collections.abc import AsyncIterator, Callable, Coroutine from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa @@ -19,6 +20,7 @@ VFolderHostPermissionMap, VFolderUsageMode, ) +from ai.backend.manager.actions.validators import ActionValidators # Statically imported so that Pants includes these modules in the test PEX. # build_root_app() loads them at runtime via importlib.import_module(), @@ -105,7 +107,9 @@ def vfolder_processors( user_repository=user_repository, valkey_stat_client=valkey_clients.stat, ) - return VFolderProcessors(service=service, action_monitors=[]) + return VFolderProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -122,7 +126,9 @@ def vfolder_file_processors( vfolder_repository=vfolder_repository, user_repository=user_repository, ) - return VFolderFileProcessors(service=service, action_monitors=[]) + return VFolderFileProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -137,7 +143,9 @@ def vfolder_invite_processors( vfolder_repository=vfolder_repository, user_repository=user_repository, ) - return VFolderInviteProcessors(service=service, action_monitors=[]) + return VFolderInviteProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() @@ -152,7 +160,9 @@ def vfolder_sharing_processors( vfolder_repository=vfolder_repository, user_repository=user_repository, ) - return VFolderSharingProcessors(service=service, action_monitors=[]) + return VFolderSharingProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/component/vfs_storage/conftest.py b/tests/component/vfs_storage/conftest.py index 9d1283eb048..1de22863ed3 100644 --- a/tests/component/vfs_storage/conftest.py +++ b/tests/component/vfs_storage/conftest.py @@ -3,11 +3,13 @@ import uuid from collections.abc import AsyncIterator, Callable, Coroutine from typing import Any +from unittest.mock import MagicMock import pytest import sqlalchemy as sa from sqlalchemy.ext.asyncio.engine import AsyncEngine as SAEngine +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.api.rest.middleware import auth as _auth_api from ai.backend.manager.api.rest.routing import RouteRegistry from ai.backend.manager.api.rest.types import RouteDeps @@ -37,7 +39,9 @@ def vfs_storage_processors( vfs_storage_repository=vfs_storage_repository, storage_manager=storage_manager, ) - return VFSStorageProcessors(service=service, action_monitors=[]) + return VFSStorageProcessors( + service=service, action_monitors=[], validators=MagicMock(spec=ActionValidators) + ) @pytest.fixture() diff --git a/tests/unit/manager/dependencies/processing/test_processors.py b/tests/unit/manager/dependencies/processing/test_processors.py index 0372d7c7432..eeb6152b462 100644 --- a/tests/unit/manager/dependencies/processing/test_processors.py +++ b/tests/unit/manager/dependencies/processing/test_processors.py @@ -3,6 +3,7 @@ from unittest.mock import MagicMock, patch from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.dependencies.processing.processors import ( ProcessorsDependency, ProcessorsProviderInput, @@ -30,6 +31,7 @@ async def test_provide_processors( action_monitors=mock_monitors, event_hub=MagicMock(), event_fetcher=MagicMock(), + validators=MagicMock(spec=ActionValidators), ) async with dependency.provide(processors_input) as processors: diff --git a/tests/unit/manager/services/container_registry/test_container_registry_service.py b/tests/unit/manager/services/container_registry/test_container_registry_service.py index 0aa488aab66..952e03340ba 100644 --- a/tests/unit/manager/services/container_registry/test_container_registry_service.py +++ b/tests/unit/manager/services/container_registry/test_container_registry_service.py @@ -13,6 +13,7 @@ from ai.backend.common.container_registry import ContainerRegistryType from ai.backend.common.types import ImageCanonical, ImageID +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.container_registry import get_container_registry_cls from ai.backend.manager.data.container_registry.types import ( ContainerRegistryData, @@ -825,7 +826,7 @@ async def test_via_processor( db=mock_db_engine, container_registry_repository=mock_container_registry_repository, ) - processors = ContainerRegistryProcessors(service, []) + processors = ContainerRegistryProcessors(service, [], MagicMock(spec=ActionValidators)) mock_container_registry_repository.search_container_registries = AsyncMock( return_value=ContainerRegistrySearchResult( diff --git a/tests/unit/manager/services/deployment/test_deployment_crud_actions.py b/tests/unit/manager/services/deployment/test_deployment_crud_actions.py index 21c3885d4c5..34fc051c87a 100644 --- a/tests/unit/manager/services/deployment/test_deployment_crud_actions.py +++ b/tests/unit/manager/services/deployment/test_deployment_crud_actions.py @@ -20,6 +20,7 @@ ReadinessStatus, ) from ai.backend.common.types import ClusterMode, ResourceSlot, RuntimeVariant, SessionId +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.data.deployment.types import ( AccessTokenSearchResult, ClusterConfigData, @@ -100,7 +101,7 @@ def deployment_service( @pytest.fixture def processors(self, deployment_service: DeploymentService) -> DeploymentProcessors: - return DeploymentProcessors(deployment_service, []) + return DeploymentProcessors(deployment_service, [], MagicMock(spec=ActionValidators)) @pytest.fixture def endpoint_id(self) -> uuid.UUID: diff --git a/tests/unit/manager/services/deployment/test_deployment_service.py b/tests/unit/manager/services/deployment/test_deployment_service.py index 82768eb278f..d22c1c29873 100644 --- a/tests/unit/manager/services/deployment/test_deployment_service.py +++ b/tests/unit/manager/services/deployment/test_deployment_service.py @@ -16,6 +16,7 @@ from ai.backend.common.data.endpoint.types import EndpointLifecycle from ai.backend.common.data.model_deployment.types import DeploymentStrategy from ai.backend.common.types import ClusterMode, ResourceSlot, RuntimeVariant +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.data.deployment.creator import ( DeploymentPolicyCreator, ModelRevisionCreator, @@ -101,7 +102,7 @@ def deployment_service( @pytest.fixture def processors(self, deployment_service: DeploymentService) -> DeploymentProcessors: """Create DeploymentProcessors with mock DeploymentService.""" - return DeploymentProcessors(deployment_service, []) + return DeploymentProcessors(deployment_service, [], MagicMock(spec=ActionValidators)) @pytest.fixture def deployment_policy_data(self) -> DeploymentPolicyData: diff --git a/tests/unit/manager/services/image/test_image_service.py b/tests/unit/manager/services/image/test_image_service.py index 56bfdfdf276..b04c691f121 100644 --- a/tests/unit/manager/services/image/test_image_service.py +++ b/tests/unit/manager/services/image/test_image_service.py @@ -20,6 +20,7 @@ from ai.backend.common.dto.agent.response import PurgeImageResp, PurgeImagesResp from ai.backend.common.exception import UnknownImageReference from ai.backend.common.types import AgentId, ImageCanonical, ImageID, SlotName +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.data.container_registry.types import ContainerRegistryData from ai.backend.manager.data.image.types import ( ImageAliasData, @@ -118,7 +119,7 @@ def image_service( @pytest.fixture def processors(self, image_service: ImageService) -> ImageProcessors: """Create ImageProcessors with mock ImageService.""" - return ImageProcessors(image_service, []) + return ImageProcessors(image_service, [], MagicMock(spec=ActionValidators)) @pytest.fixture def container_registry_id(self) -> uuid.UUID: diff --git a/tests/unit/manager/services/model_serving/actions/test_create_auto_scaling_rule.py b/tests/unit/manager/services/model_serving/actions/test_create_auto_scaling_rule.py index 578d698c51e..a7a723a1edc 100644 --- a/tests/unit/manager/services/model_serving/actions/test_create_auto_scaling_rule.py +++ b/tests/unit/manager/services/model_serving/actions/test_create_auto_scaling_rule.py @@ -15,6 +15,7 @@ EndpointId, ) from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.data.model_serving.creator import EndpointAutoScalingRuleCreator from ai.backend.manager.repositories.model_serving.repositories import ModelServingRepositories from ai.backend.manager.repositories.model_serving.repository import ModelServingRepository @@ -77,6 +78,7 @@ def auto_scaling_processors( return ModelServingAutoScalingProcessors( service=auto_scaling_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_create_model_service.py b/tests/unit/manager/services/model_serving/actions/test_create_model_service.py index 9f0972d4d56..6d05a109795 100644 --- a/tests/unit/manager/services/model_serving/actions/test_create_model_service.py +++ b/tests/unit/manager/services/model_serving/actions/test_create_model_service.py @@ -14,6 +14,7 @@ from ai.backend.common.events.hub import EventHub from ai.backend.common.types import AccessKey, ClusterMode, ResourceSlot, RuntimeVariant from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.deployment.types import ( @@ -237,6 +238,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture @@ -737,6 +739,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_delete_auto_scaling_rule.py b/tests/unit/manager/services/model_serving/actions/test_delete_auto_scaling_rule.py index 292c1296f38..07614bb8da0 100644 --- a/tests/unit/manager/services/model_serving/actions/test_delete_auto_scaling_rule.py +++ b/tests/unit/manager/services/model_serving/actions/test_delete_auto_scaling_rule.py @@ -11,6 +11,7 @@ from ai.backend.common.data.user.types import UserData, UserRole from ai.backend.common.types import RuleId from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.repositories.model_serving.repositories import ModelServingRepositories from ai.backend.manager.repositories.model_serving.repository import ModelServingRepository from ai.backend.manager.services.model_serving.actions.delete_auto_scaling_rule import ( @@ -72,6 +73,7 @@ def auto_scaling_processors( return ModelServingAutoScalingProcessors( service=auto_scaling_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_delete_model_service.py b/tests/unit/manager/services/model_serving/actions/test_delete_model_service.py index 9eff3c59d44..e30d67ee20d 100644 --- a/tests/unit/manager/services/model_serving/actions/test_delete_model_service.py +++ b/tests/unit/manager/services/model_serving/actions/test_delete_model_service.py @@ -13,6 +13,7 @@ from ai.backend.common.events.dispatcher import EventDispatcher from ai.backend.common.events.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.errors.service import ModelServiceNotFound @@ -161,6 +162,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_dry_run_model_service.py b/tests/unit/manager/services/model_serving/actions/test_dry_run_model_service.py index 99631c514b4..aad82f76b9d 100644 --- a/tests/unit/manager/services/model_serving/actions/test_dry_run_model_service.py +++ b/tests/unit/manager/services/model_serving/actions/test_dry_run_model_service.py @@ -25,6 +25,7 @@ VFolderUsageMode, ) from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.deployment.types import ( @@ -207,6 +208,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture @@ -696,6 +698,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture @@ -999,6 +1002,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_generate_token.py b/tests/unit/manager/services/model_serving/actions/test_generate_token.py index 78d1a4a050e..dbbe32fd8a6 100644 --- a/tests/unit/manager/services/model_serving/actions/test_generate_token.py +++ b/tests/unit/manager/services/model_serving/actions/test_generate_token.py @@ -16,6 +16,7 @@ from ai.backend.common.events.dispatcher import EventDispatcher from ai.backend.common.events.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.model_serving.types import EndpointTokenData @@ -164,6 +165,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_get_model_service_info.py b/tests/unit/manager/services/model_serving/actions/test_get_model_service_info.py index 8a905206bca..47be4444294 100644 --- a/tests/unit/manager/services/model_serving/actions/test_get_model_service_info.py +++ b/tests/unit/manager/services/model_serving/actions/test_get_model_service_info.py @@ -15,6 +15,7 @@ from ai.backend.common.events.hub import EventHub from ai.backend.common.types import RuntimeVariant from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.model_serving.types import ServiceInfo @@ -163,6 +164,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_list_errors.py b/tests/unit/manager/services/model_serving/actions/test_list_errors.py index e216a10180e..0655a9f8e91 100644 --- a/tests/unit/manager/services/model_serving/actions/test_list_errors.py +++ b/tests/unit/manager/services/model_serving/actions/test_list_errors.py @@ -14,6 +14,7 @@ from ai.backend.common.events.dispatcher import EventDispatcher from ai.backend.common.events.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.model_serving.types import ErrorInfo @@ -163,6 +164,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_list_model_service.py b/tests/unit/manager/services/model_serving/actions/test_list_model_service.py index acad5284d9c..b191f088c84 100644 --- a/tests/unit/manager/services/model_serving/actions/test_list_model_service.py +++ b/tests/unit/manager/services/model_serving/actions/test_list_model_service.py @@ -14,6 +14,7 @@ from ai.backend.common.events.dispatcher import EventDispatcher from ai.backend.common.events.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.model_serving.types import CompactServiceInfo @@ -163,6 +164,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_model_serving_crud_actions.py b/tests/unit/manager/services/model_serving/actions/test_model_serving_crud_actions.py index 2a388064774..4d8bd839243 100644 --- a/tests/unit/manager/services/model_serving/actions/test_model_serving_crud_actions.py +++ b/tests/unit/manager/services/model_serving/actions/test_model_serving_crud_actions.py @@ -19,6 +19,7 @@ from ai.backend.common.events.event_types.kernel.types import KernelLifecycleEventReason from ai.backend.common.events.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.model_serving.types import MutationResult @@ -183,6 +184,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_modify_auto_scaling_rule.py b/tests/unit/manager/services/model_serving/actions/test_modify_auto_scaling_rule.py index 9f9279424c2..e202a71a859 100644 --- a/tests/unit/manager/services/model_serving/actions/test_modify_auto_scaling_rule.py +++ b/tests/unit/manager/services/model_serving/actions/test_modify_auto_scaling_rule.py @@ -17,6 +17,7 @@ RuleId, ) from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.repositories.base.updater import Updater from ai.backend.manager.repositories.model_serving.repositories import ModelServingRepositories from ai.backend.manager.repositories.model_serving.repository import ModelServingRepository @@ -83,6 +84,7 @@ def auto_scaling_processors( return ModelServingAutoScalingProcessors( service=auto_scaling_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_scale_service_replicas.py b/tests/unit/manager/services/model_serving/actions/test_scale_service_replicas.py index ab0bfcc872b..a0edf660a70 100644 --- a/tests/unit/manager/services/model_serving/actions/test_scale_service_replicas.py +++ b/tests/unit/manager/services/model_serving/actions/test_scale_service_replicas.py @@ -10,6 +10,7 @@ from ai.backend.common.contexts.user import with_user from ai.backend.common.data.user.types import UserData, UserRole from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.repositories.model_serving.repositories import ModelServingRepositories from ai.backend.manager.repositories.model_serving.repository import ModelServingRepository from ai.backend.manager.services.model_serving.actions.scale_service_replicas import ( @@ -71,6 +72,7 @@ def auto_scaling_processors( return ModelServingAutoScalingProcessors( service=auto_scaling_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_search_services.py b/tests/unit/manager/services/model_serving/actions/test_search_services.py index e7dbafdd29f..24b45700c88 100644 --- a/tests/unit/manager/services/model_serving/actions/test_search_services.py +++ b/tests/unit/manager/services/model_serving/actions/test_search_services.py @@ -17,6 +17,7 @@ from ai.backend.common.events.hub import EventHub from ai.backend.common.types import ResourceSlot from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.data.model_serving.types import ( @@ -168,6 +169,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/model_serving/actions/test_update_route.py b/tests/unit/manager/services/model_serving/actions/test_update_route.py index f022f48a83b..d50c3a903f3 100644 --- a/tests/unit/manager/services/model_serving/actions/test_update_route.py +++ b/tests/unit/manager/services/model_serving/actions/test_update_route.py @@ -14,6 +14,7 @@ from ai.backend.common.events.dispatcher import EventDispatcher from ai.backend.common.events.hub import EventHub from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.clients.storage_proxy.session_manager import StorageSessionManager from ai.backend.manager.config.provider import ManagerConfigProvider from ai.backend.manager.errors.service import ModelServiceNotFound @@ -162,6 +163,7 @@ def model_serving_processors( return ModelServingProcessors( service=model_serving_service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), ) @pytest.fixture diff --git a/tests/unit/manager/services/user/test_user.py b/tests/unit/manager/services/user/test_user.py index 5119da31fc5..c51119e9d01 100644 --- a/tests/unit/manager/services/user/test_user.py +++ b/tests/unit/manager/services/user/test_user.py @@ -13,6 +13,7 @@ from ai.backend.common.clients.valkey_client.valkey_stat.client import ValkeyStatClient from ai.backend.common.types import AccessKey from ai.backend.manager.actions.monitors.monitor import ActionMonitor +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.data.auth.hash import PasswordHashAlgorithm from ai.backend.manager.data.user.types import UserInfoContext from ai.backend.manager.models.hasher.types import PasswordInfo @@ -74,6 +75,7 @@ def user_processors( return UserProcessors( user_service=user_service, action_monitors=[mock_dependencies["action_monitor"]], + validators=MagicMock(spec=ActionValidators), ) async def test_create_user_action_structure( diff --git a/tests/unit/manager/services/user_resource_policy/test_user_resource_policy.py b/tests/unit/manager/services/user_resource_policy/test_user_resource_policy.py index 9df1276dd47..bb7a1c69870 100644 --- a/tests/unit/manager/services/user_resource_policy/test_user_resource_policy.py +++ b/tests/unit/manager/services/user_resource_policy/test_user_resource_policy.py @@ -10,6 +10,7 @@ from ai.backend.common.exception import UserResourcePolicyNotFound from ai.backend.manager.actions.monitors.monitor import ActionMonitor from ai.backend.manager.actions.types import ActionOperationType +from ai.backend.manager.actions.validators import ActionValidators from ai.backend.manager.data.resource.types import UserResourcePolicyData from ai.backend.manager.repositories.base.creator import Creator from ai.backend.manager.repositories.base.updater import Updater @@ -71,6 +72,7 @@ def processors( return UserResourcePolicyProcessors( service=service, action_monitors=[mock_action_monitor], + validators=MagicMock(spec=ActionValidators), )