From fbcd44928d69ed7081e6c710f5fe6b428842a9f5 Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 13:25:37 +0200 Subject: [PATCH 1/9] Remove refs to `InfrahubServices` for git ops This change tries to remove the need for a `InfrahubServices` object when it comes to operations to be performed on a git repository. This work is a stepping stone to be able to run user flagged workflows inside a dedicated prefect worker for isolation purpose as we won't be able to inject a `InfrahubServices` object into, also we don't want to for security reasons. --- backend/infrahub/artifacts/tasks.py | 22 +-- backend/infrahub/generators/tasks.py | 2 +- backend/infrahub/git/base.py | 11 +- backend/infrahub/git/integrator.py | 10 +- backend/infrahub/git/repository.py | 40 ++---- backend/infrahub/git/tasks.py | 21 ++- .../message_bus/operations/git/file.py | 2 +- .../message_bus/operations/git/repository.py | 23 +-- backend/infrahub/proposed_change/tasks.py | 4 +- backend/infrahub/transformations/tasks.py | 4 +- backend/infrahub/webhook/models.py | 10 +- backend/infrahub/workers/dependencies.py | 136 ++++++++++++++++++ .../integration/git/test_git_repository.py | 6 +- .../tests/integration/git/test_repository.py | 2 +- 14 files changed, 195 insertions(+), 98 deletions(-) create mode 100644 backend/infrahub/workers/dependencies.py diff --git a/backend/infrahub/artifacts/tasks.py b/backend/infrahub/artifacts/tasks.py index 752f576965..c5a1b67d7f 100644 --- a/backend/infrahub/artifacts/tasks.py +++ b/backend/infrahub/artifacts/tasks.py @@ -14,21 +14,13 @@ async def create(model: CheckArtifactCreate, service: InfrahubServices) -> Valid await add_tags(branches=[model.branch_name], nodes=[model.target_id]) validator = await service.client.get(kind=InfrahubKind.ARTIFACTVALIDATOR, id=model.validator_id, include=["checks"]) - repo: InfrahubReadOnlyRepository | InfrahubRepository - if InfrahubKind.READONLYREPOSITORY: - repo = await InfrahubReadOnlyRepository.init( - id=model.repository_id, - name=model.repository_name, - client=service.client, - service=service, - ) - else: - repo = await InfrahubRepository.init( - id=model.repository_id, - name=model.repository_name, - client=service.client, - service=service, - ) + repo = await get_initialized_repo( + client=service.client, + repository_id=model.repository_id, + name=model.repository_name, + repository_kind=model.repository_kind, + commit=model.commit, + ) artifact, artifact_created = await define_artifact(model=model, service=service) diff --git a/backend/infrahub/generators/tasks.py b/backend/infrahub/generators/tasks.py index 62c682a85c..df4f213dc0 100644 --- a/backend/infrahub/generators/tasks.py +++ b/backend/infrahub/generators/tasks.py @@ -37,9 +37,9 @@ async def run_generator(model: RequestGeneratorRun, service: InfrahubServices) - await add_tags(branches=[model.branch_name], nodes=[model.target_id]) repository = await get_initialized_repo( + client=service.client, repository_id=model.repository_id, name=model.repository_name, - service=service, repository_kind=model.repository_kind, commit=model.commit, ) diff --git a/backend/infrahub/git/base.py b/backend/infrahub/git/base.py index f875308411..9ba92e4c61 100644 --- a/backend/infrahub/git/base.py +++ b/backend/infrahub/git/base.py @@ -33,7 +33,7 @@ from infrahub.git.directory import get_repositories_directory, initialize_repositories_directory from infrahub.git.worktree import Worktree from infrahub.log import get_logger -from infrahub.services import InfrahubServices # noqa: TC001 +from infrahub.workers.dependencies import get_client if TYPE_CHECKING: from infrahub_sdk.branch import BranchData @@ -153,9 +153,6 @@ class InfrahubRepositoryBase(BaseModel, ABC): ) cache_repo: Repo | None = Field(None, description="Internal cache of the GitPython Repo object") - service: InfrahubServices = Field( - ..., description="Service object with access to the message queue, the database etc.." - ) is_read_only: bool = Field(False, description="If true, changes will not be synced to remote") internal_status: str = Field("active", description="Internal status: Active, Inactive, Staging") @@ -164,10 +161,10 @@ class InfrahubRepositoryBase(BaseModel, ABC): @property def sdk(self) -> InfrahubClient: - if self.client: - return self.client + if not self.client: + self.client = get_client() - return self.service.client + return self.client @property def default_branch(self) -> str: diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index 268d2c007f..a615092c6f 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -59,7 +59,6 @@ from infrahub.artifacts.models import CheckArtifactCreate from infrahub.git.models import RequestArtifactGenerate - from infrahub.services import InfrahubServices class ArtifactGenerateResult(BaseModel): @@ -138,8 +137,8 @@ class that uses an "InfrahubRepository" or "InfrahubReadOnlyRepository" as input """ @classmethod - async def init(cls, service: InfrahubServices, commit: str | None = None, **kwargs: Any) -> Self: - self = cls(service=service, **kwargs) + async def init(cls, commit: str | None = None, **kwargs: Any) -> Self: + self = cls(**kwargs) log = get_logger() try: self.validate_local_directories() @@ -1183,7 +1182,6 @@ async def execute_python_transform( infrahub_node=InfrahubNode, ) return await transform.run(data=data) - except ModuleNotFoundError as exc: error_msg = f"Unable to load the transform file {location}" log.error(error_msg) @@ -1233,11 +1231,11 @@ async def artifact_generate( artifact_content = await self.execute_python_transform.with_options( timeout_seconds=transformation.timeout.value )( + client=self.sdk, branch_name=branch_name, commit=commit, location=transformation_location, data=response, - client=self.sdk, convert_query_response=transformation.convert_query_response.value, ) # type: ignore[misc] @@ -1293,11 +1291,11 @@ async def render_artifact( ) # type: ignore[misc] elif message.transform_type == InfrahubKind.TRANSFORMPYTHON: artifact_content = await self.execute_python_transform.with_options(timeout_seconds=message.timeout)( + client=self.sdk, branch_name=message.branch_name, commit=message.commit, location=message.transform_location, data=response, - client=self.sdk, convert_query_response=message.convert_query_response, ) # type: ignore[misc] diff --git a/backend/infrahub/git/repository.py b/backend/infrahub/git/repository.py index f6a4606ac4..3cf6c48baa 100644 --- a/backend/infrahub/git/repository.py +++ b/backend/infrahub/git/repository.py @@ -4,15 +4,17 @@ from git.exc import BadName, GitCommandError from infrahub_sdk.exceptions import GraphQLError +from prefect import task from pydantic import Field from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus from infrahub.exceptions import RepositoryError from infrahub.git.integrator import InfrahubRepositoryIntegrator from infrahub.log import get_logger +from infrahub.services import InfrahubServices # noqa: TC001 if TYPE_CHECKING: - from infrahub.services import InfrahubServices + from infrahub_sdk.client import InfrahubClient log = get_logger() @@ -25,10 +27,8 @@ class InfrahubRepository(InfrahubRepositoryIntegrator): """ @classmethod - async def new( - cls, service: InfrahubServices, update_commit_value: bool = True, **kwargs: Any - ) -> InfrahubRepository: - self = cls(service=service, **kwargs) + async def new(cls, update_commit_value: bool = True, **kwargs: Any) -> InfrahubRepository: + self = cls(**kwargs) await self.create_locally( infrahub_branch_name=self.infrahub_branch_name, update_commit_value=update_commit_value ) @@ -248,33 +248,17 @@ async def sync_from_remote(self, commit: str | None = None) -> None: await self.update_commit_value(branch_name=self.infrahub_branch_name, commit=commit) +@task( + name="Fetch repository commit", + description="Retrieve a git repository at a given commit, if it does not already exist locally", +) async def get_initialized_repo( - repository_id: str, name: str, service: InfrahubServices, repository_kind: str, commit: str | None = None + client: InfrahubClient, repository_id: str, name: str, repository_kind: str, commit: str | None = None ) -> InfrahubReadOnlyRepository | InfrahubRepository: if repository_kind == InfrahubKind.REPOSITORY: - return await InfrahubRepository.init( - id=repository_id, name=name, commit=commit, client=service._client, service=service - ) + return await InfrahubRepository.init(id=repository_id, name=name, commit=commit, client=client) if repository_kind == InfrahubKind.READONLYREPOSITORY: - return await InfrahubReadOnlyRepository.init( - id=repository_id, name=name, commit=commit, client=service._client, service=service - ) - - raise NotImplementedError(f"The repository kind {repository_kind} has not been implemented") - - -async def initialize_repo( - location: str, repository_id: str, name: str, service: InfrahubServices, repository_kind: str -) -> InfrahubReadOnlyRepository | InfrahubRepository: - if repository_kind == InfrahubKind.REPOSITORY: - return await InfrahubRepository.new( - location=location, id=repository_id, name=name, client=service._client, service=service - ) - - if repository_kind == InfrahubKind.READONLYREPOSITORY: - return await InfrahubReadOnlyRepository.new( - location=location, id=repository_id, name=name, client=service._client, service=service - ) + return await InfrahubReadOnlyRepository.init(id=repository_id, name=name, commit=commit, client=client) raise NotImplementedError(f"The repository kind {repository_kind} has not been implemented") diff --git a/backend/infrahub/git/tasks.py b/backend/infrahub/git/tasks.py index 27362c5291..98f6714629 100644 --- a/backend/infrahub/git/tasks.py +++ b/backend/infrahub/git/tasks.py @@ -273,9 +273,9 @@ async def generate_artifact(model: RequestArtifactGenerate, service: InfrahubSer await add_tags(branches=[model.branch_name], nodes=[model.target_id]) log = get_run_logger() repo = await get_initialized_repo( + client=service.client, repository_id=model.repository_id, name=model.repository_name, - service=service, repository_kind=model.repository_kind, commit=model.commit, ) @@ -477,9 +477,9 @@ async def merge_git_repository(model: GitRepositoryMerge, service: InfrahubServi async def import_objects_from_git_repository(model: GitRepositoryImportObjects, service: InfrahubServices) -> None: await add_branch_tag(model.infrahub_branch_name) repo = await get_initialized_repo( + client=service.client, repository_id=model.repository_id, name=model.repository_name, - service=service, repository_kind=model.repository_kind, commit=model.commit, ) @@ -495,9 +495,9 @@ async def git_repository_diff_names_only( model: GitDiffNamesOnly, service: InfrahubServices ) -> GitDiffNamesOnlyResponse: repo = await get_initialized_repo( + client=service.client, repository_id=model.repository_id, name=model.repository_name, - service=service, repository_kind=model.repository_kind, ) files_changed: list[str] = [] @@ -756,7 +756,12 @@ async def run_check_merge_conflicts( validator = await service.client.get(kind=InfrahubKind.REPOSITORYVALIDATOR, id=model.validator_id) await validator.checks.fetch() - repo = await InfrahubRepository.init(id=model.repository_id, name=model.repository_name, service=service) + repo = await get_initialized_repo( + client=service.client, + repository_id=model.repository_id, + name=model.repository_name, + repository_kind=InfrahubKind.REPOSITORY, + ) async with lock.registry.get(name=model.repository_name, namespace="repository"): conflicts = await repo.get_conflicts(source_branch=model.source_branch, dest_branch=model.target_branch) @@ -830,8 +835,12 @@ async def run_user_check(model: UserCheckData, service: InfrahubServices) -> Val validator = await service.client.get(kind=InfrahubKind.USERVALIDATOR, id=model.validator_id) await validator.checks.fetch() - repo = await InfrahubRepository.init( - id=model.repository_id, name=model.repository_name, commit=model.commit, service=service + repo = await get_initialized_repo( + client=service.client, + repository_id=model.repository_id, + name=model.repository_name, + repository_kind=InfrahubKind.REPOSITORY, + commit=model.commit, ) conclusion = ValidatorConclusion.FAILURE severity = "critical" diff --git a/backend/infrahub/message_bus/operations/git/file.py b/backend/infrahub/message_bus/operations/git/file.py index a3a5dbc79c..89c990305a 100644 --- a/backend/infrahub/message_bus/operations/git/file.py +++ b/backend/infrahub/message_bus/operations/git/file.py @@ -15,9 +15,9 @@ async def get(message: messages.GitFileGet, service: InfrahubServices) -> None: log.info("Collecting file from repository", repository=message.repository_name, file=message.file) repo = await get_initialized_repo( + client=service.client, repository_id=message.repository_id, name=message.repository_name, - service=service, repository_kind=message.repository_kind, commit=message.commit, ) diff --git a/backend/infrahub/message_bus/operations/git/repository.py b/backend/infrahub/message_bus/operations/git/repository.py index eb6b874eac..7e6d2de6ae 100644 --- a/backend/infrahub/message_bus/operations/git/repository.py +++ b/backend/infrahub/message_bus/operations/git/repository.py @@ -1,7 +1,7 @@ from prefect import flow from infrahub.exceptions import RepositoryError -from infrahub.git.repository import InfrahubRepository, get_initialized_repo, initialize_repo +from infrahub.git.repository import InfrahubRepository, get_initialized_repo from infrahub.log import get_logger from infrahub.message_bus import messages from infrahub.message_bus.messages.git_repository_connectivity import ( @@ -37,21 +37,12 @@ async def fetch(message: messages.RefreshGitFetch, service: InfrahubServices) -> log.info("Ignoring git fetch request originating from self", worker=WORKER_IDENTITY) return - try: - repo = await get_initialized_repo( - repository_id=message.repository_id, - name=message.repository_name, - service=service, - repository_kind=message.repository_kind, - ) - except RepositoryError: - repo = await initialize_repo( - location=message.location, - repository_id=message.repository_id, - name=message.repository_name, - service=service, - repository_kind=message.repository_kind, - ) + repo = await get_initialized_repo( + client=service.client, + repository_id=message.repository_id, + name=message.repository_name, + repository_kind=message.repository_kind, + ) await repo.fetch() await repo.pull( diff --git a/backend/infrahub/proposed_change/tasks.py b/backend/infrahub/proposed_change/tasks.py index cc5f7b0172..4c7d2aaa2c 100644 --- a/backend/infrahub/proposed_change/tasks.py +++ b/backend/infrahub/proposed_change/tasks.py @@ -554,9 +554,9 @@ def _execute( for repository in model.branch_diff.repositories: if model.source_branch_sync_with_git: repo = await get_initialized_repo( + client=service.client, repository_id=repository.repository_id, name=repository.repository_name, - service=service, repository_kind=repository.kind, ) commit = repo.get_commit_value(proposed_change.source_branch.value) @@ -706,9 +706,9 @@ async def run_generator_as_check( log = get_run_logger() repository = await get_initialized_repo( + client=service.client, repository_id=model.repository_id, name=model.repository_name, - service=service, repository_kind=model.repository_kind, commit=model.commit, ) diff --git a/backend/infrahub/transformations/tasks.py b/backend/infrahub/transformations/tasks.py index 7e2cd4e2bd..bf1e8090f4 100644 --- a/backend/infrahub/transformations/tasks.py +++ b/backend/infrahub/transformations/tasks.py @@ -17,9 +17,9 @@ async def transform_python(message: TransformPythonData, service: InfrahubServic await add_branch_tag(branch_name=message.branch) repo = await get_initialized_repo( + client=service.client, repository_id=message.repository_id, name=message.repository_name, - service=service, repository_kind=message.repository_kind, commit=message.commit, ) @@ -41,9 +41,9 @@ async def transform_render_jinja2_template(message: TransformJinjaTemplateData, await add_branch_tag(branch_name=message.branch) repo = await get_initialized_repo( + client=service.client, repository_id=message.repository_id, name=message.repository_name, - service=service, repository_kind=message.repository_kind, commit=message.commit, ) diff --git a/backend/infrahub/webhook/models.py b/backend/infrahub/webhook/models.py index 87558d27e2..476d24b661 100644 --- a/backend/infrahub/webhook/models.py +++ b/backend/infrahub/webhook/models.py @@ -210,17 +210,11 @@ async def _prepare_payload(self, data: dict[str, Any], context: EventContext, se repo: InfrahubReadOnlyRepository | InfrahubRepository if self.repository_kind == InfrahubKind.READONLYREPOSITORY: repo = await InfrahubReadOnlyRepository.init( - id=self.repository_id, - name=self.repository_name, - client=service.client, - service=service, + id=self.repository_id, name=self.repository_name, client=service.client ) else: repo = await InfrahubRepository.init( - id=self.repository_id, - name=self.repository_name, - client=service.client, - service=service, + id=self.repository_id, name=self.repository_name, client=service.client ) branch = context.branch or repo.default_branch diff --git a/backend/infrahub/workers/dependencies.py b/backend/infrahub/workers/dependencies.py new file mode 100644 index 0000000000..472df1ff75 --- /dev/null +++ b/backend/infrahub/workers/dependencies.py @@ -0,0 +1,136 @@ +from fast_depends import Depends, inject +from infrahub_sdk.client import InfrahubClient +from infrahub_sdk.config import Config + +from infrahub import config +from infrahub.components import ComponentType +from infrahub.database import InfrahubDatabase, get_db +from infrahub.services import InfrahubServices +from infrahub.services.adapters.cache import InfrahubCache +from infrahub.services.adapters.event import InfrahubEventService +from infrahub.services.adapters.http import InfrahubHTTP +from infrahub.services.adapters.http.httpx import HttpxAdapter +from infrahub.services.adapters.message_bus import InfrahubMessageBus +from infrahub.services.adapters.workflow import InfrahubWorkflow +from infrahub.services.adapters.workflow.local import WorkflowLocalExecution +from infrahub.services.adapters.workflow.worker import WorkflowWorkerExecution + +client: InfrahubClient | None = None +database: InfrahubDatabase | None = None +cache: InfrahubCache | None = None +message_bus: InfrahubMessageBus | None = None +event_service: InfrahubEventService | None = None +workflow: InfrahubWorkflow | None = None +http: InfrahubHTTP | None = None +services: InfrahubServices | None = None + + +def build_client() -> InfrahubClient: + global client + if client is None: + client = InfrahubClient(config=Config(address=config.SETTINGS.main.internal_address, retry_on_failure=True)) + return client + + +@inject +def get_client(client: InfrahubClient = Depends(build_client)) -> InfrahubClient: # noqa: B008 + return client + + +async def build_database() -> InfrahubDatabase: + global database + if database is None: + database = InfrahubDatabase(driver=await get_db(retry=1)) + return database + + +@inject +async def get_database(database: InfrahubDatabase = Depends(build_database)) -> InfrahubDatabase: # noqa: B008 + return database + + +async def build_cache() -> InfrahubCache: + global cache + if cache is None: + cache = config.OVERRIDE.cache or (await InfrahubCache.new_from_driver(driver=config.SETTINGS.cache.driver)) + return cache + + +@inject +async def get_cache(cache: InfrahubCache = Depends(build_cache)) -> InfrahubCache: # noqa: B008 + return cache + + +async def build_message_bus() -> InfrahubMessageBus: + global message_bus + if message_bus is None: + message_bus = config.OVERRIDE.message_bus or ( + await InfrahubMessageBus.new_from_driver( + component_type=ComponentType.GIT_AGENT, driver=config.SETTINGS.broker.driver + ) + ) + return message_bus + + +@inject +async def get_message_bus(message_bus: InfrahubMessageBus = Depends(build_message_bus)) -> InfrahubMessageBus: # noqa: B008 + return message_bus + + +@inject +async def build_event_service() -> InfrahubEventService: + global event_service + if event_service is None: + event_service = InfrahubEventService(message_bus=await get_message_bus()) + return event_service + + +@inject +async def get_event_service(event_service: InfrahubEventService = Depends(build_event_service)) -> InfrahubEventService: # noqa: B008 + return event_service + + +def build_workflow() -> InfrahubWorkflow: + global workflow + if workflow is None: + workflow = config.OVERRIDE.workflow or ( + WorkflowWorkerExecution() + if config.SETTINGS.workflow.driver == config.WorkflowDriver.WORKER + else WorkflowLocalExecution() + ) + return workflow + + +@inject +def get_workflow(workflow: InfrahubWorkflow = Depends(build_workflow)) -> InfrahubWorkflow: # noqa: B008 + return workflow + + +def build_http() -> InfrahubHTTP: + global http + if http is None: + http = HttpxAdapter() + return http + + +@inject +def get_http(http: InfrahubHTTP = Depends(build_http)) -> InfrahubHTTP: # noqa: B008 + return http + + +async def get_infrahub_services() -> InfrahubServices: + # We have some form a circular dependency between: + # 1. InfrahubServuces and InfrahubMessageBus + # 2. InfrahubServices and InfrahubWorkflow + global services + if services is None: + services = await InfrahubServices.new( + cache=await get_cache(), + client=get_client(), + database=await get_database(), + message_bus=await get_message_bus(), + workflow=get_workflow(), + component_type=ComponentType.GIT_AGENT, + ) + + return services diff --git a/backend/tests/integration/git/test_git_repository.py b/backend/tests/integration/git/test_git_repository.py index e72c9573b3..5089023ce6 100644 --- a/backend/tests/integration/git/test_git_repository.py +++ b/backend/tests/integration/git/test_git_repository.py @@ -311,11 +311,7 @@ async def test_get_missing_file(self, db: InfrahubDatabase, client: InfrahubClie # Initialize the repository on the file system repo = await InfrahubRepository.new( - id=obj.id, - name=git_repo_car_dealership.name, - location=git_repo_car_dealership.path, - client=client, - service=await InfrahubServices.new(database=db), + id=obj.id, name=git_repo_car_dealership.name, location=git_repo_car_dealership.path, client=client ) commit = repo.get_commit_value(branch_name="main") diff --git a/backend/tests/integration/git/test_repository.py b/backend/tests/integration/git/test_repository.py index 0077666108..07eba85e83 100644 --- a/backend/tests/integration/git/test_repository.py +++ b/backend/tests/integration/git/test_repository.py @@ -101,9 +101,9 @@ async def test_repository_operational_status( assert repository.commit.value infrahub_repo = await get_initialized_repo( + client=client, repository_id=repository.id, name=repository.name.value, - service=service, repository_kind=InfrahubKind.REPOSITORY, ) From 1b04133fdbcae37c398eee26941182cc3474a91b Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 13:27:00 +0200 Subject: [PATCH 2/9] Add `fast_depends` to requirements --- poetry.lock | 31 +++++++++++++++++++++++-------- pyproject.toml | 3 +-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index 534446fa93..375b19d670 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aio-pika" @@ -1133,6 +1133,21 @@ files = [ python-dateutil = ">=2.4" typing-extensions = "*" +[[package]] +name = "fast-depends" +version = "2.4.12" +description = "FastDepends - extracted and cleared from HTTP domain logic FastAPI Dependency Injection System. Async and sync are both supported." +optional = false +python-versions = ">=3.8" +files = [ + {file = "fast_depends-2.4.12-py3-none-any.whl", hash = "sha256:9e5d110ddc962329e46c9b35e5fe65655984247a13ee3ca5a33186db7d2d75c2"}, + {file = "fast_depends-2.4.12.tar.gz", hash = "sha256:9393e6de827f7afa0141e54fa9553b737396aaf06bd0040e159d1f790487b16d"}, +] + +[package.dependencies] +anyio = ">=3.0.0,<5.0.0" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<3.0.0" + [[package]] name = "fastapi" version = "0.115.10" @@ -4763,24 +4778,24 @@ python-versions = ">=3.6" files = [ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:d92f81886165cb14d7b067ef37e142256f1c6a90a65cd156b063a43da1708cfd"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:b5edda50e5e9e15e54a6a8a0070302b00c518a9d32accc2346ad6c984aacd279"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:7048c338b6c86627afb27faecf418768acb6331fc24cfa56c93e8c9780f815fa"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, @@ -4788,7 +4803,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3fcc54cb0c8b811ff66082de1680b4b14cf8a81dce0d4fbf665c2265a81e07a1"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, @@ -4796,7 +4811,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:665f58bfd29b167039f714c6998178d27ccd83984084c286110ef26b230f259f"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, @@ -4804,7 +4819,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9eb5dee2772b0f704ca2e45b1713e4e5198c18f515b52743576d196348f374d3"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, @@ -6042,4 +6057,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.10, < 3.13" -content-hash = "0c4a872c691816ac14d05c63a94e0b58690fe8ecdc894b2c96a9c5d83996916b" +content-hash = "e13c3f254c1a84cc75c50d23a7d38a34bca378350c857429390e9143b4b93d0e" diff --git a/pyproject.toml b/pyproject.toml index 97e2e3f3f4..26734edd23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,7 @@ nats-py = "^2.7.2" netaddr = "1.3.0" authlib = "1.3.2" aiodataloader = "0.4.0" - +fast-depends = "^2.4.12" # Dependencies specific to the SDK rich = "^13" @@ -76,7 +76,6 @@ dulwich = "^0.22.7" whenever = "0.7.2" netutils = "1.12.0" - [tool.poetry.group.dev.dependencies] yamllint = "*" mypy = "*" From 46de9607b8237dd3323b7b996cc17e434c74cbe1 Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 13:52:28 +0200 Subject: [PATCH 3/9] Missing import --- backend/infrahub/artifacts/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/infrahub/artifacts/tasks.py b/backend/infrahub/artifacts/tasks.py index c5a1b67d7f..e2fd050b71 100644 --- a/backend/infrahub/artifacts/tasks.py +++ b/backend/infrahub/artifacts/tasks.py @@ -3,7 +3,7 @@ from infrahub.artifacts.models import CheckArtifactCreate from infrahub.core.constants import InfrahubKind, ValidatorConclusion from infrahub.core.timestamp import Timestamp -from infrahub.git import InfrahubReadOnlyRepository, InfrahubRepository +from infrahub.git.repository import get_initialized_repo from infrahub.services import InfrahubServices from infrahub.tasks.artifact import define_artifact from infrahub.workflows.utils import add_tags From a7242d3234ff0ad6030eea460984e7469f1372ef Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 14:39:00 +0200 Subject: [PATCH 4/9] Remove service refs from some tests --- backend/tests/unit/git/conftest.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/backend/tests/unit/git/conftest.py b/backend/tests/unit/git/conftest.py index f6e32a5033..6a406b7d91 100644 --- a/backend/tests/unit/git/conftest.py +++ b/backend/tests/unit/git/conftest.py @@ -18,7 +18,6 @@ from infrahub.core.schema import SchemaRoot, core_models from infrahub.git import InfrahubRepository from infrahub.git.repository import InfrahubReadOnlyRepository -from infrahub.services import InfrahubServices from infrahub.utils import find_first_file_in_directory, get_fixtures_dir from tests.conftest import TestHelper from tests.helpers.test_client import dummy_async_request @@ -138,7 +137,6 @@ async def git_repo_01( name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) return repo @@ -157,7 +155,6 @@ async def git_repo_01_read_only( ref="branch01", infrahub_branch_name="main", client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) return repo @@ -179,7 +176,6 @@ async def git_repo_02(git_upstream_repo_02: dict[str, str | Path], git_repos_dir name=git_upstream_repo_02["name"], location=str(git_upstream_repo_02["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) return repo @@ -204,7 +200,6 @@ async def git_repo_03( name=git_upstream_repo_03["name"], location=str(git_upstream_repo_03["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) return repo @@ -233,7 +228,6 @@ async def git_repo_04( name=git_upstream_repo_03["name"], location=str(git_upstream_repo_03["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) await repo.create_branch_in_git(branch_name=branch01.name, branch_id=branch01.id) @@ -271,7 +265,6 @@ async def git_repo_05( name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) # Update the first file at the top level and commit the change in the branch @@ -303,7 +296,6 @@ async def git_repo_06( name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) await repo.create_branch_in_git(branch_name=branch01.name, branch_id=branch01.id) @@ -399,7 +391,6 @@ async def git_repo_jinja( name=git_upstream_repo_02["name"], location=str(git_upstream_repo_02["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) await repo.create_branch_in_git(branch_name=branch01.name, branch_id=branch01.id) @@ -438,7 +429,6 @@ async def git_repo_checks( name=git_upstream_repo_02["name"], location=str(git_upstream_repo_02["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) return repo @@ -469,7 +459,6 @@ async def git_repo_transforms( name=git_upstream_repo_02["name"], location=str(git_upstream_repo_02["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) return repo @@ -493,7 +482,6 @@ async def git_repo_10( name=git_upstream_repo_10["name"], location=str(git_upstream_repo_10["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) repo.client = client From 25f430986d6944588a497ddc00a4a12d7bc6fb82 Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 14:41:35 +0200 Subject: [PATCH 5/9] Remove left over service reference --- backend/infrahub/git/integrator.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index a615092c6f..0bc9948b23 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -48,6 +48,7 @@ from infrahub.exceptions import CheckError, RepositoryInvalidFileSystemError, TransformError from infrahub.git.base import InfrahubRepositoryBase, extract_repo_file_information from infrahub.log import get_logger +from infrahub.workers.dependencies import get_event_service from infrahub.workflows.utils import add_tags if TYPE_CHECKING: @@ -208,7 +209,8 @@ async def import_objects_from_files( raise error infrahub_branch = registry.get_branch_from_registry(branch=infrahub_branch_name) - await self.service.event.send( + event_service = await get_event_service() + await event_service.send( CommitUpdatedEvent( commit=commit, repository_name=self.name, @@ -1338,5 +1340,6 @@ async def render_artifact( storage_id_previous=previous_storage_id, ) - await self.service.event.send(event=event) + event_service = await get_event_service() + await event_service.send(event=event) return ArtifactGenerateResult(changed=True, checksum=checksum, storage_id=storage_id, artifact_id=artifact.id) From dbaadf96bee790c1cae877ea9761beceb7978a27 Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 14:59:51 +0200 Subject: [PATCH 6/9] Replace service by client in repo init for computed attr --- backend/infrahub/computed_attribute/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/infrahub/computed_attribute/tasks.py b/backend/infrahub/computed_attribute/tasks.py index 7c585bde67..c833a74133 100644 --- a/backend/infrahub/computed_attribute/tasks.py +++ b/backend/infrahub/computed_attribute/tasks.py @@ -92,9 +92,9 @@ async def process_transform( ) repo = await get_initialized_repo( + client=service.client, repository_id=transform.repository.peer.id, name=transform.repository.peer.name.value, - service=service, repository_kind=str(transform.repository.peer.typename), commit=repo_node.commit.value, ) # type: ignore[misc] From d83beee0e017f10b504f1137c2e0451a735fd59e Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Mon, 5 May 2025 15:30:24 +0200 Subject: [PATCH 7/9] Remove service ref for RO repo --- backend/infrahub/git/repository.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/infrahub/git/repository.py b/backend/infrahub/git/repository.py index 3cf6c48baa..00b3c42e94 100644 --- a/backend/infrahub/git/repository.py +++ b/backend/infrahub/git/repository.py @@ -11,7 +11,6 @@ from infrahub.exceptions import RepositoryError from infrahub.git.integrator import InfrahubRepositoryIntegrator from infrahub.log import get_logger -from infrahub.services import InfrahubServices # noqa: TC001 if TYPE_CHECKING: from infrahub_sdk.client import InfrahubClient @@ -209,11 +208,11 @@ class InfrahubReadOnlyRepository(InfrahubRepositoryIntegrator): ref: str | None = Field(None, description="Ref to track on the external repository") @classmethod - async def new(cls, service: InfrahubServices, **kwargs: Any) -> InfrahubReadOnlyRepository: + async def new(cls, **kwargs: Any) -> InfrahubReadOnlyRepository: if "ref" not in kwargs or "infrahub_branch_name" not in kwargs: raise ValueError("ref and infrahub_branch_name are mandatory to initialize a new Read-Only repository") - self = cls(service=service, **kwargs) + self = cls(**kwargs) await self.create_locally(checkout_ref=self.ref, infrahub_branch_name=self.infrahub_branch_name) log.info("Created new repository locally.", repository=self.name) return self From a2904ffb27400fe564f10dc99e92823fa14b364e Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Wed, 7 May 2025 14:40:34 +0200 Subject: [PATCH 8/9] Remove some more service refs in git tests --- backend/tests/unit/git/test_git_repository.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/backend/tests/unit/git/test_git_repository.py b/backend/tests/unit/git/test_git_repository.py index 81e3c1989c..9acc601954 100644 --- a/backend/tests/unit/git/test_git_repository.py +++ b/backend/tests/unit/git/test_git_repository.py @@ -32,7 +32,6 @@ CheckDefinitionInformation, ) from infrahub.git.worktree import Worktree -from infrahub.services import InfrahubServices from infrahub.utils import find_first_file_in_directory from tests.conftest import TestHelper from tests.helpers.file_repo import MultipleStagesFileRepo @@ -51,7 +50,6 @@ async def test_directories_props(git_upstream_repo_01: dict[str, str | Path], gi name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) assert repo.directory_root == git_repos_dir / str(repo.id) @@ -66,7 +64,6 @@ async def test_new_empty_dir(git_upstream_repo_01: dict[str, str | Path], git_re name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) # Check if all the directories are present @@ -86,7 +83,6 @@ async def test_new_existing_directory(git_upstream_repo_01: dict[str, str | Path name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) # Check if all the directories are present @@ -105,7 +101,6 @@ async def test_new_existing_file(git_upstream_repo_01: dict[str, str | Path], gi name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), client=InfrahubClient(config=Config(requester=dummy_async_request)), - service=await InfrahubServices.new(), ) # Check if all the directories are present @@ -121,7 +116,7 @@ async def test_new_wrong_location(git_upstream_repo_01: dict[str, str | Path], g id=UUIDT.new(), name=git_upstream_repo_01["name"], location=str(tmp_path), - service=await InfrahubServices.new(client=InfrahubClient(config=Config(requester=dummy_async_request))), + client=InfrahubClient(config=Config(requester=dummy_async_request)), ) assert f"fatal: repository '{tmp_path}' does not exist" in str(exc.value) @@ -134,14 +129,14 @@ async def test_new_wrong_branch(git_upstream_repo_01: dict[str, str | Path], git name=git_upstream_repo_01["name"], location=str(git_upstream_repo_01["path"]), default_branch_name="notvalid", - service=await InfrahubServices.new(client=InfrahubClient(config=Config(requester=dummy_async_request))), + client=InfrahubClient(config=Config(requester=dummy_async_request)), ) assert "isn't a valid branch" in str(exc.value) async def test_init_existing_repository(git_repo_01: InfrahubRepository): - repo = await InfrahubRepository.init(id=git_repo_01.id, name=git_repo_01.name, service=await InfrahubServices.new()) + repo = await InfrahubRepository.init(id=git_repo_01.id, name=git_repo_01.name) # Check if all the directories are present assert repo.has_origin is True From 9da3379a2136d343f749591049fe1e76a071739e Mon Sep 17 00:00:00 2001 From: Guillaume Mazoyer Date: Thu, 8 May 2025 14:42:39 +0200 Subject: [PATCH 9/9] Rewrite singletons to only have one private var --- backend/infrahub/workers/dependencies.py | 81 ++++++++++-------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/backend/infrahub/workers/dependencies.py b/backend/infrahub/workers/dependencies.py index 472df1ff75..0dbc78a571 100644 --- a/backend/infrahub/workers/dependencies.py +++ b/backend/infrahub/workers/dependencies.py @@ -1,3 +1,5 @@ +from typing import Any + from fast_depends import Depends, inject from infrahub_sdk.client import InfrahubClient from infrahub_sdk.config import Config @@ -15,21 +17,15 @@ from infrahub.services.adapters.workflow.local import WorkflowLocalExecution from infrahub.services.adapters.workflow.worker import WorkflowWorkerExecution -client: InfrahubClient | None = None -database: InfrahubDatabase | None = None -cache: InfrahubCache | None = None -message_bus: InfrahubMessageBus | None = None -event_service: InfrahubEventService | None = None -workflow: InfrahubWorkflow | None = None -http: InfrahubHTTP | None = None -services: InfrahubServices | None = None +_singletons: dict[str, Any] = {} def build_client() -> InfrahubClient: - global client - if client is None: - client = InfrahubClient(config=Config(address=config.SETTINGS.main.internal_address, retry_on_failure=True)) - return client + if "client" not in _singletons: + _singletons["client"] = InfrahubClient( + config=Config(address=config.SETTINGS.main.internal_address, retry_on_failure=True) + ) + return _singletons["client"] @inject @@ -38,10 +34,9 @@ def get_client(client: InfrahubClient = Depends(build_client)) -> InfrahubClient async def build_database() -> InfrahubDatabase: - global database - if database is None: - database = InfrahubDatabase(driver=await get_db(retry=1)) - return database + if "database" not in _singletons: + _singletons["database"] = InfrahubDatabase(driver=await get_db(retry=1)) + return _singletons["database"] @inject @@ -50,10 +45,11 @@ async def get_database(database: InfrahubDatabase = Depends(build_database)) -> async def build_cache() -> InfrahubCache: - global cache - if cache is None: - cache = config.OVERRIDE.cache or (await InfrahubCache.new_from_driver(driver=config.SETTINGS.cache.driver)) - return cache + if "cache" not in _singletons: + _singletons["cache"] = config.OVERRIDE.cache or await InfrahubCache.new_from_driver( + driver=config.SETTINGS.cache.driver + ) + return _singletons["cache"] @inject @@ -62,14 +58,13 @@ async def get_cache(cache: InfrahubCache = Depends(build_cache)) -> InfrahubCach async def build_message_bus() -> InfrahubMessageBus: - global message_bus - if message_bus is None: - message_bus = config.OVERRIDE.message_bus or ( + if "message_bus" not in _singletons: + _singletons["message_bus"] = config.OVERRIDE.message_bus or ( await InfrahubMessageBus.new_from_driver( component_type=ComponentType.GIT_AGENT, driver=config.SETTINGS.broker.driver ) ) - return message_bus + return _singletons["message_bus"] @inject @@ -77,12 +72,10 @@ async def get_message_bus(message_bus: InfrahubMessageBus = Depends(build_messag return message_bus -@inject async def build_event_service() -> InfrahubEventService: - global event_service - if event_service is None: - event_service = InfrahubEventService(message_bus=await get_message_bus()) - return event_service + if "event_service" not in _singletons: + _singletons["event_service"] = InfrahubEventService(message_bus=await get_message_bus()) + return _singletons["event_service"] @inject @@ -91,14 +84,13 @@ async def get_event_service(event_service: InfrahubEventService = Depends(build_ def build_workflow() -> InfrahubWorkflow: - global workflow - if workflow is None: - workflow = config.OVERRIDE.workflow or ( + if "workflow" not in _singletons: + _singletons["workflow"] = config.OVERRIDE.workflow or ( WorkflowWorkerExecution() if config.SETTINGS.workflow.driver == config.WorkflowDriver.WORKER else WorkflowLocalExecution() ) - return workflow + return _singletons["workflow"] @inject @@ -106,25 +98,20 @@ def get_workflow(workflow: InfrahubWorkflow = Depends(build_workflow)) -> Infrah return workflow -def build_http() -> InfrahubHTTP: - global http - if http is None: - http = HttpxAdapter() - return http +def build_http_service() -> InfrahubHTTP: + if "http_service" not in _singletons: + _singletons["http_service"] = HttpxAdapter() + return _singletons["http_service"] @inject -def get_http(http: InfrahubHTTP = Depends(build_http)) -> InfrahubHTTP: # noqa: B008 - return http +def get_http(http_service: InfrahubHTTP = Depends(build_http_service)) -> InfrahubHTTP: # noqa: B008 + return http_service async def get_infrahub_services() -> InfrahubServices: - # We have some form a circular dependency between: - # 1. InfrahubServuces and InfrahubMessageBus - # 2. InfrahubServices and InfrahubWorkflow - global services - if services is None: - services = await InfrahubServices.new( + if "services" not in _singletons: + _singletons["services"] = await InfrahubServices.new( cache=await get_cache(), client=get_client(), database=await get_database(), @@ -133,4 +120,4 @@ async def get_infrahub_services() -> InfrahubServices: component_type=ComponentType.GIT_AGENT, ) - return services + return _singletons["services"]