infrahub-server 1.5.5__py3-none-any.whl → 1.6.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/api/artifact.py +5 -3
- infrahub/auth.py +5 -6
- infrahub/cli/db.py +3 -3
- infrahub/cli/db_commands/clean_duplicate_schema_fields.py +2 -2
- infrahub/cli/dev.py +30 -0
- infrahub/config.py +62 -14
- infrahub/constants/database.py +5 -5
- infrahub/core/branch/models.py +24 -6
- infrahub/core/diff/model/diff.py +2 -2
- infrahub/core/graph/constraints.py +2 -2
- infrahub/core/manager.py +155 -29
- infrahub/core/merge.py +29 -2
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +2 -3
- infrahub/core/migrations/shared.py +2 -2
- infrahub/core/node/__init__.py +1 -1
- infrahub/core/node/ipam.py +4 -4
- infrahub/core/node/node_property_attribute.py +2 -2
- infrahub/core/protocols.py +7 -1
- infrahub/core/query/branch.py +11 -0
- infrahub/core/query/standard_node.py +3 -0
- infrahub/core/relationship/model.py +3 -9
- infrahub/core/schema/__init__.py +3 -3
- infrahub/core/task/user_task.py +2 -2
- infrahub/core/validators/enum.py +2 -2
- infrahub/dependencies/interface.py +2 -2
- infrahub/events/constants.py +2 -2
- infrahub/git/base.py +43 -1
- infrahub/git/models.py +2 -1
- infrahub/git/repository.py +5 -1
- infrahub/git/tasks.py +28 -1
- infrahub/git/utils.py +9 -0
- infrahub/graphql/analyzer.py +4 -4
- infrahub/graphql/mutations/computed_attribute.py +1 -1
- infrahub/graphql/mutations/convert_object_type.py +1 -1
- infrahub/graphql/mutations/display_label.py +1 -1
- infrahub/graphql/mutations/hfid.py +1 -1
- infrahub/graphql/mutations/ipam.py +1 -1
- infrahub/graphql/mutations/profile.py +1 -0
- infrahub/graphql/mutations/relationship.py +2 -2
- infrahub/graphql/mutations/resource_manager.py +1 -1
- infrahub/graphql/queries/__init__.py +2 -1
- infrahub/graphql/queries/branch.py +58 -3
- infrahub/graphql/queries/ipam.py +9 -4
- infrahub/graphql/queries/resource_manager.py +5 -8
- infrahub/graphql/queries/search.py +3 -3
- infrahub/graphql/schema.py +2 -0
- infrahub/graphql/types/__init__.py +3 -1
- infrahub/graphql/types/branch.py +98 -2
- infrahub/lock.py +6 -6
- infrahub/patch/constants.py +2 -2
- infrahub/task_manager/task.py +2 -2
- infrahub/telemetry/constants.py +2 -2
- infrahub/trigger/models.py +2 -2
- infrahub/utils.py +1 -1
- infrahub/validators/tasks.py +1 -1
- infrahub/workers/infrahub_async.py +37 -0
- infrahub_sdk/async_typer.py +2 -1
- infrahub_sdk/batch.py +2 -2
- infrahub_sdk/client.py +8 -9
- infrahub_sdk/config.py +2 -2
- infrahub_sdk/ctl/branch.py +1 -1
- infrahub_sdk/ctl/cli.py +2 -2
- infrahub_sdk/ctl/cli_commands.py +2 -1
- infrahub_sdk/ctl/graphql.py +2 -2
- infrahub_sdk/ctl/importer.py +1 -1
- infrahub_sdk/ctl/utils.py +3 -3
- infrahub_sdk/node/attribute.py +11 -10
- infrahub_sdk/node/constants.py +1 -2
- infrahub_sdk/node/node.py +54 -11
- infrahub_sdk/node/related_node.py +1 -1
- infrahub_sdk/object_store.py +4 -4
- infrahub_sdk/operation.py +2 -2
- infrahub_sdk/protocols_generator/generator.py +1 -1
- infrahub_sdk/pytest_plugin/items/jinja2_transform.py +1 -1
- infrahub_sdk/pytest_plugin/models.py +1 -1
- infrahub_sdk/pytest_plugin/plugin.py +1 -1
- infrahub_sdk/query_groups.py +2 -2
- infrahub_sdk/schema/__init__.py +10 -11
- infrahub_sdk/schema/main.py +2 -2
- infrahub_sdk/schema/repository.py +2 -2
- infrahub_sdk/spec/object.py +2 -2
- infrahub_sdk/spec/range_expansion.py +1 -1
- infrahub_sdk/template/__init__.py +2 -1
- infrahub_sdk/transfer/importer/json.py +3 -3
- infrahub_sdk/types.py +2 -2
- infrahub_sdk/utils.py +2 -2
- {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info}/METADATA +58 -59
- {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info}/RECORD +217 -223
- {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info}/WHEEL +1 -1
- infrahub_server-1.6.0b0.dist-info/entry_points.txt +12 -0
- infrahub_testcontainers/docker-compose-cluster.test.yml +1 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub/core/schema/generated/__init__.py +0 -0
- infrahub/core/schema/generated/attribute_schema.py +0 -133
- infrahub/core/schema/generated/base_node_schema.py +0 -111
- infrahub/core/schema/generated/genericnode_schema.py +0 -30
- infrahub/core/schema/generated/node_schema.py +0 -40
- infrahub/core/schema/generated/relationship_schema.py +0 -141
- infrahub_server-1.5.5.dist-info/entry_points.txt +0 -13
- {infrahub_server-1.5.5.dist-info → infrahub_server-1.6.0b0.dist-info/licenses}/LICENSE.txt +0 -0
infrahub/git/base.py
CHANGED
|
@@ -16,10 +16,12 @@ from prefect.logging import get_run_logger
|
|
|
16
16
|
from pydantic import BaseModel, ConfigDict, Field
|
|
17
17
|
from pydantic import ValidationError as PydanticValidationError
|
|
18
18
|
|
|
19
|
+
from infrahub import config
|
|
19
20
|
from infrahub.core.branch import Branch
|
|
20
21
|
from infrahub.core.constants import InfrahubKind, RepositoryOperationalStatus, RepositorySyncStatus
|
|
21
22
|
from infrahub.core.registry import registry
|
|
22
23
|
from infrahub.exceptions import (
|
|
24
|
+
BranchNotFoundError,
|
|
23
25
|
CommitNotFoundError,
|
|
24
26
|
FileOutOfRepositoryError,
|
|
25
27
|
RepositoryConnectionError,
|
|
@@ -31,6 +33,7 @@ from infrahub.exceptions import (
|
|
|
31
33
|
)
|
|
32
34
|
from infrahub.git.constants import BRANCHES_DIRECTORY_NAME, COMMITS_DIRECTORY_NAME, TEMPORARY_DIRECTORY_NAME
|
|
33
35
|
from infrahub.git.directory import get_repositories_directory, initialize_repositories_directory
|
|
36
|
+
from infrahub.git.utils import branch_name_in_import_sync_branches
|
|
34
37
|
from infrahub.git.worktree import Worktree
|
|
35
38
|
from infrahub.log import get_logger
|
|
36
39
|
from infrahub.workers.dependencies import get_client
|
|
@@ -733,6 +736,45 @@ class InfrahubRepositoryBase(BaseModel, ABC):
|
|
|
733
736
|
|
|
734
737
|
return True
|
|
735
738
|
|
|
739
|
+
async def get_filtered_remote_branches(self) -> dict[str, BranchInRemote]:
|
|
740
|
+
branches = self.get_branches_from_remote()
|
|
741
|
+
|
|
742
|
+
if not config.SETTINGS.git.import_sync_branch_names:
|
|
743
|
+
return branches
|
|
744
|
+
|
|
745
|
+
filtered_branches = {}
|
|
746
|
+
skipped_branch_names = []
|
|
747
|
+
|
|
748
|
+
for short_name, branch_data in branches.items():
|
|
749
|
+
branch = None
|
|
750
|
+
|
|
751
|
+
try:
|
|
752
|
+
branch = registry.get_branch_from_registry(branch=short_name)
|
|
753
|
+
except BranchNotFoundError:
|
|
754
|
+
...
|
|
755
|
+
|
|
756
|
+
branch_exists_import_sync_condition = branch and (
|
|
757
|
+
branch.name not in {registry.default_branch, self.default_branch}
|
|
758
|
+
and not branch.sync_with_git
|
|
759
|
+
and not branch_name_in_import_sync_branches(branch_short_name=short_name)
|
|
760
|
+
)
|
|
761
|
+
branch_does_not_exist_import_sync_condition = not branch and not branch_name_in_import_sync_branches(
|
|
762
|
+
branch_short_name=short_name
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
if branch_exists_import_sync_condition or branch_does_not_exist_import_sync_condition:
|
|
766
|
+
skipped_branch_names.append(short_name)
|
|
767
|
+
continue
|
|
768
|
+
|
|
769
|
+
filtered_branches[short_name] = branch_data
|
|
770
|
+
|
|
771
|
+
if skipped_branch_names:
|
|
772
|
+
log.debug(
|
|
773
|
+
f"Skipped the following branches {skipped_branch_names} "
|
|
774
|
+
f"because no match was found in import_sync_branch_names {config.SETTINGS.git.import_sync_branch_names}"
|
|
775
|
+
)
|
|
776
|
+
return filtered_branches
|
|
777
|
+
|
|
736
778
|
async def compare_local_remote(self) -> tuple[list[str], list[str]]:
|
|
737
779
|
"""
|
|
738
780
|
Returns:
|
|
@@ -745,7 +787,7 @@ class InfrahubRepositoryBase(BaseModel, ABC):
|
|
|
745
787
|
# TODO move this section into a dedicated function to compare and bring in sync the remote repo with the local one.
|
|
746
788
|
# It can be useful just after a clone etc ...
|
|
747
789
|
local_branches = self.get_branches_from_local()
|
|
748
|
-
remote_branches = self.
|
|
790
|
+
remote_branches = await self.get_filtered_remote_branches()
|
|
749
791
|
|
|
750
792
|
new_branches = set(remote_branches.keys()) - set(local_branches.keys())
|
|
751
793
|
existing_branches = set(local_branches.keys()) - new_branches
|
infrahub/git/models.py
CHANGED
|
@@ -92,7 +92,8 @@ class GitRepositoryMerge(BaseModel):
|
|
|
92
92
|
source_branch: str = Field(..., description="The source branch")
|
|
93
93
|
destination_branch: str = Field(..., description="The destination branch")
|
|
94
94
|
destination_branch_id: str = Field(..., description="The ID of the destination branch")
|
|
95
|
-
default_branch: str = Field(
|
|
95
|
+
default_branch: str | None = Field(default=None, description="The default branch in Git")
|
|
96
|
+
repository_kind: str = Field(..., description="The kind of the repository.")
|
|
96
97
|
|
|
97
98
|
|
|
98
99
|
class GitRepositoryImportObjects(BaseModel):
|
infrahub/git/repository.py
CHANGED
|
@@ -11,6 +11,7 @@ from prefect import task
|
|
|
11
11
|
from prefect.cache_policies import NONE
|
|
12
12
|
from pydantic import Field
|
|
13
13
|
|
|
14
|
+
from infrahub import config
|
|
14
15
|
from infrahub.core.constants import InfrahubKind, RepositoryInternalStatus
|
|
15
16
|
from infrahub.exceptions import RepositoryError
|
|
16
17
|
from infrahub.git.integrator import InfrahubRepositoryIntegrator
|
|
@@ -170,7 +171,10 @@ class InfrahubRepository(InfrahubRepositoryIntegrator):
|
|
|
170
171
|
commit = self.get_commit_value(branch_name=source_branch, remote=False)
|
|
171
172
|
|
|
172
173
|
try:
|
|
173
|
-
|
|
174
|
+
if config.SETTINGS.git.use_explicit_merge_commit:
|
|
175
|
+
repo.git.merge(commit, "--no-ff", m="Merged by Infrahub")
|
|
176
|
+
else:
|
|
177
|
+
repo.git.merge(commit)
|
|
174
178
|
except GitCommandError as exc:
|
|
175
179
|
repo.git.merge("--abort")
|
|
176
180
|
raise RepositoryError(identifier=self.name, message=exc.stderr) from exc
|
infrahub/git/tasks.py
CHANGED
|
@@ -502,6 +502,7 @@ async def pull_read_only(model: GitRepositoryPullReadOnly) -> None:
|
|
|
502
502
|
flow_run_name="Merge {model.source_branch} > {model.destination_branch} in git repository",
|
|
503
503
|
)
|
|
504
504
|
async def merge_git_repository(model: GitRepositoryMerge) -> None:
|
|
505
|
+
log = get_run_logger()
|
|
505
506
|
await add_tags(branches=[model.source_branch, model.destination_branch], nodes=[model.repository_id])
|
|
506
507
|
|
|
507
508
|
client = get_client()
|
|
@@ -510,7 +511,11 @@ async def merge_git_repository(model: GitRepositoryMerge) -> None:
|
|
|
510
511
|
id=model.repository_id, name=model.repository_name, client=client, default_branch_name=model.default_branch
|
|
511
512
|
)
|
|
512
513
|
|
|
513
|
-
if
|
|
514
|
+
if (
|
|
515
|
+
model.internal_status == RepositoryInternalStatus.STAGING.value
|
|
516
|
+
and model.repository_kind == InfrahubKind.REPOSITORY
|
|
517
|
+
):
|
|
518
|
+
log.info(f"Merging {model.repository_kind}")
|
|
514
519
|
repo_source = await client.get(
|
|
515
520
|
kind=InfrahubKind.GENERICREPOSITORY, id=model.repository_id, branch=model.source_branch
|
|
516
521
|
)
|
|
@@ -522,6 +527,28 @@ async def merge_git_repository(model: GitRepositoryMerge) -> None:
|
|
|
522
527
|
repo_main.commit.value = commit
|
|
523
528
|
|
|
524
529
|
await repo_main.save()
|
|
530
|
+
log.info(f"Finished merging {model.repository_kind}")
|
|
531
|
+
|
|
532
|
+
elif model.repository_kind == InfrahubKind.READONLYREPOSITORY:
|
|
533
|
+
repo_source = await client.get(
|
|
534
|
+
kind=InfrahubKind.READONLYREPOSITORY, id=model.repository_id, branch=model.source_branch
|
|
535
|
+
)
|
|
536
|
+
repo_destination = await client.get(
|
|
537
|
+
kind=InfrahubKind.READONLYREPOSITORY, id=model.repository_id, branch=model.destination_branch
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
if (
|
|
541
|
+
repo_destination.ref.value != repo_source.ref.value
|
|
542
|
+
or repo_destination.commit.value != repo_source.commit.value
|
|
543
|
+
):
|
|
544
|
+
log.info(f"Merging {model.repository_kind}")
|
|
545
|
+
|
|
546
|
+
repo_destination.ref.value = repo_source.ref.value
|
|
547
|
+
repo_destination.commit.value = repo_source.commit.value
|
|
548
|
+
await repo_destination.save()
|
|
549
|
+
|
|
550
|
+
log.info(f"Finished merging {model.repository_kind}")
|
|
551
|
+
|
|
525
552
|
else:
|
|
526
553
|
async with lock.registry.get(name=model.repository_name, namespace="repository"):
|
|
527
554
|
await repo.merge(source_branch=model.source_branch, dest_branch=model.destination_branch)
|
infrahub/git/utils.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import re
|
|
1
2
|
from collections import defaultdict
|
|
2
3
|
from typing import TYPE_CHECKING, Any
|
|
3
4
|
|
|
@@ -12,6 +13,7 @@ from infrahub.core.manager import NodeManager
|
|
|
12
13
|
from infrahub.database import InfrahubDatabase
|
|
13
14
|
from infrahub.generators.models import ProposedChangeGeneratorDefinition
|
|
14
15
|
|
|
16
|
+
from .. import config
|
|
15
17
|
from .models import RepositoryBranchInfo, RepositoryData
|
|
16
18
|
|
|
17
19
|
if TYPE_CHECKING:
|
|
@@ -168,3 +170,10 @@ async def fetch_proposed_change_generator_definition_targets(
|
|
|
168
170
|
return await _fetch_definition_targets(
|
|
169
171
|
client=client, branch=branch, group_id=definition.group_id, parameters=definition.parameters
|
|
170
172
|
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def branch_name_in_import_sync_branches(branch_short_name: str) -> bool:
|
|
176
|
+
for branch_filter in config.SETTINGS.git.import_sync_branch_names:
|
|
177
|
+
if re.fullmatch(branch_filter, branch_short_name) or branch_filter == branch_short_name:
|
|
178
|
+
return True
|
|
179
|
+
return False
|
infrahub/graphql/analyzer.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from collections import deque
|
|
4
4
|
from copy import deepcopy
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
|
-
from enum import
|
|
6
|
+
from enum import StrEnum
|
|
7
7
|
from functools import cached_property
|
|
8
8
|
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
@@ -49,13 +49,13 @@ if TYPE_CHECKING:
|
|
|
49
49
|
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
class MutateAction(
|
|
52
|
+
class MutateAction(StrEnum):
|
|
53
53
|
CREATE = "create"
|
|
54
54
|
DELETE = "delete"
|
|
55
55
|
UPDATE = "update"
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
class ContextType(
|
|
58
|
+
class ContextType(StrEnum):
|
|
59
59
|
EDGE = "edge"
|
|
60
60
|
NODE = "node"
|
|
61
61
|
DIRECT = "direct"
|
|
@@ -80,7 +80,7 @@ class ContextType(str, Enum):
|
|
|
80
80
|
return cls.NODE
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
class GraphQLOperation(
|
|
83
|
+
class GraphQLOperation(StrEnum):
|
|
84
84
|
QUERY = "query"
|
|
85
85
|
MUTATION = "mutation"
|
|
86
86
|
SUBSCRIPTION = "subscription"
|
|
@@ -110,7 +110,7 @@ class UpdateComputedAttribute(Mutation):
|
|
|
110
110
|
event = NodeUpdatedEvent(
|
|
111
111
|
kind=node_schema.kind,
|
|
112
112
|
node_id=target_node.get_id(),
|
|
113
|
-
changelog=target_node.node_changelog
|
|
113
|
+
changelog=target_node.node_changelog,
|
|
114
114
|
fields=[str(data.attribute)],
|
|
115
115
|
meta=EventMeta(
|
|
116
116
|
context=graphql_context.get_context(),
|
|
@@ -76,7 +76,7 @@ class ConvertObjectType(Mutation):
|
|
|
76
76
|
|
|
77
77
|
if target_schema.kind in [REPOSITORY, READONLYREPOSITORY]:
|
|
78
78
|
new_node = await convert_repository_type(
|
|
79
|
-
repository=node_to_convert,
|
|
79
|
+
repository=node_to_convert, # type: ignore[arg-type]
|
|
80
80
|
target_schema=target_schema,
|
|
81
81
|
mapping=fields_mapping,
|
|
82
82
|
branch=graphql_context.branch,
|
|
@@ -101,7 +101,7 @@ class UpdateDisplayLabel(Mutation):
|
|
|
101
101
|
event = NodeUpdatedEvent(
|
|
102
102
|
kind=node_schema.kind,
|
|
103
103
|
node_id=target_node.get_id(),
|
|
104
|
-
changelog=target_node.node_changelog
|
|
104
|
+
changelog=target_node.node_changelog,
|
|
105
105
|
fields=["display_label"],
|
|
106
106
|
meta=EventMeta(
|
|
107
107
|
context=graphql_context.get_context(),
|
|
@@ -108,7 +108,7 @@ class UpdateHFID(Mutation):
|
|
|
108
108
|
event = NodeUpdatedEvent(
|
|
109
109
|
kind=node_schema.kind,
|
|
110
110
|
node_id=target_node.get_id(),
|
|
111
|
-
changelog=target_node.node_changelog
|
|
111
|
+
changelog=target_node.node_changelog,
|
|
112
112
|
fields=["human_friendly_id"],
|
|
113
113
|
meta=EventMeta(
|
|
114
114
|
context=graphql_context.get_context(),
|
|
@@ -48,7 +48,7 @@ async def validate_namespace(
|
|
|
48
48
|
namespace_id = namespace.id
|
|
49
49
|
elif "hfid" in data["ip_namespace"]:
|
|
50
50
|
namespace = await registry.manager.get_one_by_hfid(
|
|
51
|
-
db=db, branch=branch, kind=InfrahubKind.IPNAMESPACE, hfid=data["ip_namespace"]["hfid"]
|
|
51
|
+
db=db, branch=branch, kind=InfrahubKind.IPNAMESPACE, hfid=data["ip_namespace"]["hfid"], raise_on_error=True
|
|
52
52
|
)
|
|
53
53
|
namespace_id = namespace.id
|
|
54
54
|
else:
|
|
@@ -186,6 +186,7 @@ class InfrahubProfilesRefresh(Mutation):
|
|
|
186
186
|
branch=branch,
|
|
187
187
|
id=str(data.id),
|
|
188
188
|
include_source=True,
|
|
189
|
+
raise_on_error=True,
|
|
189
190
|
)
|
|
190
191
|
node_profiles_applier = NodeProfilesApplier(db=db, branch=branch)
|
|
191
192
|
updated_fields = await node_profiles_applier.apply_profiles(node=obj)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from enum import
|
|
3
|
+
from enum import StrEnum
|
|
4
4
|
from typing import TYPE_CHECKING, Self
|
|
5
5
|
|
|
6
6
|
from graphene import Boolean, InputField, InputObjectType, List, Mutation, String
|
|
@@ -48,7 +48,7 @@ if TYPE_CHECKING:
|
|
|
48
48
|
RELATIONSHIP_PEERS_TO_IGNORE = [InfrahubKind.NODE]
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
class GroupUpdateType(
|
|
51
|
+
class GroupUpdateType(StrEnum):
|
|
52
52
|
NONE = "none"
|
|
53
53
|
MEMBERS = "members"
|
|
54
54
|
MEMBER_OF_GROUPS = "member_of_groups"
|
|
@@ -122,7 +122,7 @@ class IPAddressPoolGetResource(Mutation):
|
|
|
122
122
|
) -> Self:
|
|
123
123
|
graphql_context: GraphqlContext = info.context
|
|
124
124
|
|
|
125
|
-
obj: CoreIPAddressPool = await registry.manager.find_object(
|
|
125
|
+
obj: CoreIPAddressPool = await registry.manager.find_object( # type: ignore[assignment]
|
|
126
126
|
db=graphql_context.db,
|
|
127
127
|
kind=InfrahubKind.IPADDRESSPOOL,
|
|
128
128
|
id=data.get("id"),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .account import AccountPermissions, AccountToken
|
|
2
|
-
from .branch import BranchQueryList
|
|
2
|
+
from .branch import BranchQueryList, InfrahubBranchQueryList
|
|
3
3
|
from .internal import InfrahubInfo
|
|
4
4
|
from .ipam import (
|
|
5
5
|
DeprecatedIPAddressGetNextAvailable,
|
|
@@ -20,6 +20,7 @@ __all__ = [
|
|
|
20
20
|
"BranchQueryList",
|
|
21
21
|
"DeprecatedIPAddressGetNextAvailable",
|
|
22
22
|
"DeprecatedIPPrefixGetNextAvailable",
|
|
23
|
+
"InfrahubBranchQueryList",
|
|
23
24
|
"InfrahubIPAddressGetNextAvailable",
|
|
24
25
|
"InfrahubIPPrefixGetNextAvailable",
|
|
25
26
|
"InfrahubInfo",
|
|
@@ -2,10 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
|
-
from graphene import ID, Field, List, NonNull, String
|
|
5
|
+
from graphene import ID, Field, Int, List, NonNull, String
|
|
6
6
|
|
|
7
|
+
from infrahub.core.registry import registry
|
|
8
|
+
from infrahub.exceptions import ValidationError
|
|
7
9
|
from infrahub.graphql.field_extractor import extract_graphql_fields
|
|
8
|
-
from infrahub.graphql.types import BranchType
|
|
10
|
+
from infrahub.graphql.types import BranchType, InfrahubBranch, InfrahubBranchType
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
13
|
from graphql import GraphQLResolveInfo
|
|
@@ -17,7 +19,7 @@ async def branch_resolver(
|
|
|
17
19
|
**kwargs: Any,
|
|
18
20
|
) -> list[dict[str, Any]]:
|
|
19
21
|
fields = extract_graphql_fields(info)
|
|
20
|
-
return await BranchType.get_list(graphql_context=info.context, fields=fields, **kwargs)
|
|
22
|
+
return await BranchType.get_list(graphql_context=info.context, fields=fields, exclude_global=True, **kwargs)
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
BranchQueryList = Field(
|
|
@@ -28,3 +30,56 @@ BranchQueryList = Field(
|
|
|
28
30
|
resolver=branch_resolver,
|
|
29
31
|
required=True,
|
|
30
32
|
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
async def infrahub_branch_resolver(
|
|
36
|
+
root: dict, # noqa: ARG001
|
|
37
|
+
info: GraphQLResolveInfo,
|
|
38
|
+
limit: int | None = None,
|
|
39
|
+
offset: int | None = None,
|
|
40
|
+
name__value: str | None = None,
|
|
41
|
+
ids: list[str] | None = None,
|
|
42
|
+
) -> dict[str, Any]:
|
|
43
|
+
if isinstance(limit, int) and limit < 1:
|
|
44
|
+
raise ValidationError("limit must be >= 1")
|
|
45
|
+
if isinstance(offset, int) and offset < 0:
|
|
46
|
+
raise ValidationError("offset must be >= 0")
|
|
47
|
+
|
|
48
|
+
fields = extract_graphql_fields(info)
|
|
49
|
+
result: dict[str, Any] = {}
|
|
50
|
+
if "edges" in fields:
|
|
51
|
+
branches = await InfrahubBranch.get_list(
|
|
52
|
+
graphql_context=info.context,
|
|
53
|
+
fields=fields.get("edges", {}).get("node", {}),
|
|
54
|
+
limit=limit,
|
|
55
|
+
offset=offset,
|
|
56
|
+
name=name__value,
|
|
57
|
+
ids=ids,
|
|
58
|
+
exclude_global=True,
|
|
59
|
+
)
|
|
60
|
+
result["edges"] = [{"node": branch} for branch in branches]
|
|
61
|
+
if "count" in fields:
|
|
62
|
+
result["count"] = await InfrahubBranchType.get_list_count(
|
|
63
|
+
graphql_context=info.context, name=name__value, ids=ids
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if "default_branch" in fields:
|
|
67
|
+
result["default_branch"] = await InfrahubBranch.get_by_name(
|
|
68
|
+
graphql_context=info.context,
|
|
69
|
+
fields=fields["default_branch"],
|
|
70
|
+
name=registry.default_branch,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return result
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
InfrahubBranchQueryList = Field(
|
|
77
|
+
InfrahubBranchType,
|
|
78
|
+
offset=Int(),
|
|
79
|
+
limit=Int(),
|
|
80
|
+
name__value=String(),
|
|
81
|
+
ids=List(ID),
|
|
82
|
+
description="Retrieve paginated information about active branches.",
|
|
83
|
+
resolver=infrahub_branch_resolver,
|
|
84
|
+
required=True,
|
|
85
|
+
)
|
infrahub/graphql/queries/ipam.py
CHANGED
|
@@ -8,6 +8,7 @@ from netaddr import IPSet
|
|
|
8
8
|
|
|
9
9
|
from infrahub.core.constants import InfrahubKind
|
|
10
10
|
from infrahub.core.manager import NodeManager
|
|
11
|
+
from infrahub.core.protocols import BuiltinIPPrefix
|
|
11
12
|
from infrahub.core.query.ipam import get_ip_addresses, get_subnets
|
|
12
13
|
from infrahub.exceptions import NodeNotFoundError, ValidationError
|
|
13
14
|
from infrahub.pools.address import get_available
|
|
@@ -31,7 +32,9 @@ class IPAddressGetNextAvailable(ObjectType):
|
|
|
31
32
|
) -> dict[str, str]:
|
|
32
33
|
graphql_context: GraphqlContext = info.context
|
|
33
34
|
|
|
34
|
-
prefix = await NodeManager.get_one(
|
|
35
|
+
prefix = await NodeManager.get_one(
|
|
36
|
+
id=prefix_id, kind=BuiltinIPPrefix, db=graphql_context.db, branch=graphql_context.branch
|
|
37
|
+
)
|
|
35
38
|
|
|
36
39
|
if not prefix:
|
|
37
40
|
raise NodeNotFoundError(
|
|
@@ -78,17 +81,19 @@ class IPPrefixGetNextAvailable(ObjectType):
|
|
|
78
81
|
) -> dict[str, str]:
|
|
79
82
|
graphql_context: GraphqlContext = info.context
|
|
80
83
|
|
|
81
|
-
prefix = await NodeManager.get_one(
|
|
84
|
+
prefix = await NodeManager.get_one(
|
|
85
|
+
id=prefix_id, db=graphql_context.db, branch=graphql_context.branch, kind=BuiltinIPPrefix
|
|
86
|
+
)
|
|
82
87
|
|
|
83
88
|
if not prefix:
|
|
84
89
|
raise NodeNotFoundError(
|
|
85
90
|
branch_name=graphql_context.branch.name, node_type=InfrahubKind.IPPREFIX, identifier=prefix_id
|
|
86
91
|
)
|
|
87
92
|
|
|
88
|
-
namespace = await prefix.ip_namespace.get_peer(db=graphql_context.db)
|
|
93
|
+
namespace = await prefix.ip_namespace.get_peer(db=graphql_context.db)
|
|
89
94
|
subnets = await get_subnets(
|
|
90
95
|
db=graphql_context.db,
|
|
91
|
-
ip_prefix=ipaddress.ip_network(prefix.prefix.value),
|
|
96
|
+
ip_prefix=ipaddress.ip_network(prefix.prefix.value),
|
|
92
97
|
namespace=namespace,
|
|
93
98
|
branch=graphql_context.branch,
|
|
94
99
|
)
|
|
@@ -23,7 +23,6 @@ if TYPE_CHECKING:
|
|
|
23
23
|
|
|
24
24
|
from infrahub.core.branch import Branch
|
|
25
25
|
from infrahub.core.node import Node
|
|
26
|
-
from infrahub.core.protocols import CoreNode
|
|
27
26
|
from infrahub.core.timestamp import Timestamp
|
|
28
27
|
from infrahub.database import InfrahubDatabase
|
|
29
28
|
from infrahub.graphql.initialization import GraphqlContext
|
|
@@ -59,7 +58,7 @@ class PoolAllocatedEdge(ObjectType):
|
|
|
59
58
|
node = Field(PoolAllocatedNode, required=True)
|
|
60
59
|
|
|
61
60
|
|
|
62
|
-
def _validate_pool_type(pool_id: str, pool:
|
|
61
|
+
def _validate_pool_type(pool_id: str, pool: Node | None = None) -> Node:
|
|
63
62
|
if not pool or pool.get_kind() not in [
|
|
64
63
|
InfrahubKind.IPADDRESSPOOL,
|
|
65
64
|
InfrahubKind.IPPREFIXPOOL,
|
|
@@ -83,9 +82,7 @@ class PoolAllocated(ObjectType):
|
|
|
83
82
|
limit: int = 10,
|
|
84
83
|
) -> dict:
|
|
85
84
|
graphql_context: GraphqlContext = info.context
|
|
86
|
-
pool
|
|
87
|
-
id=pool_id, db=graphql_context.db, branch=graphql_context.branch
|
|
88
|
-
)
|
|
85
|
+
pool = await NodeManager.get_one(id=pool_id, db=graphql_context.db, branch=graphql_context.branch)
|
|
89
86
|
|
|
90
87
|
fields = extract_graphql_fields(info=info)
|
|
91
88
|
|
|
@@ -190,7 +187,7 @@ class PoolUtilization(ObjectType):
|
|
|
190
187
|
) -> dict:
|
|
191
188
|
graphql_context: GraphqlContext = info.context
|
|
192
189
|
db: InfrahubDatabase = graphql_context.db
|
|
193
|
-
pool
|
|
190
|
+
pool = await NodeManager.get_one(id=pool_id, db=db, branch=graphql_context.branch)
|
|
194
191
|
pool = _validate_pool_type(pool_id=pool_id, pool=pool)
|
|
195
192
|
if pool.get_kind() == "CoreNumberPool":
|
|
196
193
|
return await resolve_number_pool_utilization(
|
|
@@ -275,7 +272,7 @@ class PoolUtilization(ObjectType):
|
|
|
275
272
|
|
|
276
273
|
|
|
277
274
|
async def resolve_number_pool_allocation(
|
|
278
|
-
db: InfrahubDatabase, graphql_context: GraphqlContext, pool:
|
|
275
|
+
db: InfrahubDatabase, graphql_context: GraphqlContext, pool: Node, fields: dict, offset: int, limit: int
|
|
279
276
|
) -> dict:
|
|
280
277
|
response: dict[str, Any] = {}
|
|
281
278
|
query = await NumberPoolGetAllocated.init(
|
|
@@ -304,7 +301,7 @@ async def resolve_number_pool_allocation(
|
|
|
304
301
|
|
|
305
302
|
|
|
306
303
|
async def resolve_number_pool_utilization(
|
|
307
|
-
db: InfrahubDatabase, pool:
|
|
304
|
+
db: InfrahubDatabase, pool: Node, at: Timestamp | str | None, branch: Branch
|
|
308
305
|
) -> dict:
|
|
309
306
|
"""
|
|
310
307
|
Returns a mapping containg utilization info of a number pool.
|
|
@@ -13,7 +13,7 @@ from infrahub.graphql.field_extractor import extract_graphql_fields
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
14
|
from graphql import GraphQLResolveInfo
|
|
15
15
|
|
|
16
|
-
from infrahub.core.
|
|
16
|
+
from infrahub.core.node import Node as InfrahubNode
|
|
17
17
|
from infrahub.graphql.initialization import GraphqlContext
|
|
18
18
|
|
|
19
19
|
|
|
@@ -106,12 +106,12 @@ async def search_resolver(
|
|
|
106
106
|
) -> dict[str, Any]:
|
|
107
107
|
graphql_context: GraphqlContext = info.context
|
|
108
108
|
response: dict[str, Any] = {}
|
|
109
|
-
results: list[
|
|
109
|
+
results: list[InfrahubNode] = []
|
|
110
110
|
|
|
111
111
|
fields = extract_graphql_fields(info=info)
|
|
112
112
|
|
|
113
113
|
if is_valid_uuid(q):
|
|
114
|
-
matching
|
|
114
|
+
matching = await NodeManager.get_one(
|
|
115
115
|
db=graphql_context.db, branch=graphql_context.branch, at=graphql_context.at, id=q
|
|
116
116
|
)
|
|
117
117
|
if matching:
|
infrahub/graphql/schema.py
CHANGED
|
@@ -39,6 +39,7 @@ from .queries import (
|
|
|
39
39
|
BranchQueryList,
|
|
40
40
|
DeprecatedIPAddressGetNextAvailable,
|
|
41
41
|
DeprecatedIPPrefixGetNextAvailable,
|
|
42
|
+
InfrahubBranchQueryList,
|
|
42
43
|
InfrahubInfo,
|
|
43
44
|
InfrahubIPAddressGetNextAvailable,
|
|
44
45
|
InfrahubIPPrefixGetNextAvailable,
|
|
@@ -65,6 +66,7 @@ class InfrahubBaseQuery(ObjectType):
|
|
|
65
66
|
|
|
66
67
|
Relationship = Relationship
|
|
67
68
|
|
|
69
|
+
InfrahubBranch = InfrahubBranchQueryList
|
|
68
70
|
InfrahubInfo = InfrahubInfo
|
|
69
71
|
InfrahubStatus = InfrahubStatus
|
|
70
72
|
|
|
@@ -21,7 +21,7 @@ from .attribute import (
|
|
|
21
21
|
StrAttributeType,
|
|
22
22
|
TextAttributeType,
|
|
23
23
|
)
|
|
24
|
-
from .branch import BranchType
|
|
24
|
+
from .branch import BranchType, InfrahubBranch, InfrahubBranchType
|
|
25
25
|
from .interface import InfrahubInterface
|
|
26
26
|
from .node import InfrahubObject
|
|
27
27
|
from .permission import PaginatedObjectPermission
|
|
@@ -41,6 +41,8 @@ __all__ = [
|
|
|
41
41
|
"DropdownType",
|
|
42
42
|
"IPHostType",
|
|
43
43
|
"IPNetworkType",
|
|
44
|
+
"InfrahubBranch",
|
|
45
|
+
"InfrahubBranchType",
|
|
44
46
|
"InfrahubInterface",
|
|
45
47
|
"InfrahubObject",
|
|
46
48
|
"InfrahubObjectType",
|