infrahub-server 1.1.6__py3-none-any.whl → 1.1.7__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/core/attribute.py +4 -1
- infrahub/core/branch/tasks.py +7 -4
- infrahub/core/diff/combiner.py +11 -7
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +1 -6
- infrahub/core/diff/enricher/labels.py +13 -3
- infrahub/core/diff/enricher/path_identifier.py +2 -8
- infrahub/core/diff/merger/merger.py +5 -3
- infrahub/core/diff/model/path.py +42 -24
- infrahub/core/diff/query/all_conflicts.py +5 -2
- infrahub/core/diff/query/diff_get.py +2 -1
- infrahub/core/diff/query/field_specifiers.py +2 -0
- infrahub/core/diff/query/field_summary.py +2 -1
- infrahub/core/diff/query/filters.py +12 -1
- infrahub/core/diff/query/has_conflicts_query.py +5 -2
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +3 -3
- infrahub/core/diff/query/roots_metadata.py +8 -1
- infrahub/core/diff/query/save.py +148 -63
- infrahub/core/diff/query/summary_counts_enricher.py +220 -0
- infrahub/core/diff/query/time_range_query.py +2 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +23 -24
- infrahub/core/diff/repository/repository.py +76 -20
- infrahub/core/node/__init__.py +6 -1
- infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
- infrahub/core/node/ipam.py +6 -1
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/query/diff.py +41 -3
- infrahub/core/query/node.py +8 -2
- infrahub/core/query/relationship.py +2 -1
- infrahub/core/query/resource_manager.py +3 -1
- infrahub/core/utils.py +1 -0
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +13 -0
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/graphql/mutations/computed_attribute.py +3 -1
- infrahub/graphql/mutations/diff.py +28 -4
- infrahub/graphql/mutations/main.py +11 -6
- infrahub/graphql/mutations/relationship.py +29 -1
- infrahub/graphql/mutations/tasks.py +6 -3
- infrahub/graphql/queries/resource_manager.py +7 -3
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/types.py +26 -0
- infrahub_sdk/batch.py +2 -2
- infrahub_sdk/config.py +1 -1
- infrahub_sdk/ctl/check.py +1 -1
- infrahub_sdk/ctl/utils.py +2 -2
- infrahub_sdk/data.py +1 -1
- infrahub_sdk/node.py +4 -1
- infrahub_sdk/protocols.py +1 -0
- infrahub_sdk/schema/__init__.py +3 -0
- infrahub_sdk/testing/docker.py +0 -30
- infrahub_sdk/transfer/exporter/json.py +1 -1
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.7.dist-info}/METADATA +41 -7
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.7.dist-info}/RECORD +65 -65
- infrahub_testcontainers/container.py +12 -3
- infrahub_testcontainers/docker-compose.test.yml +22 -3
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/diff/enricher/summary_counts.py +0 -105
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +0 -8
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.7.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.7.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.7.dist-info}/entry_points.txt +0 -0
|
@@ -87,7 +87,9 @@ class UpdateComputedAttribute(Mutation):
|
|
|
87
87
|
log_data = get_log_data()
|
|
88
88
|
request_id = log_data.get("request_id", "")
|
|
89
89
|
|
|
90
|
-
graphql_payload = await target_node.to_graphql(
|
|
90
|
+
graphql_payload = await target_node.to_graphql(
|
|
91
|
+
db=context.db, filter_sensitive=True, include_properties=False
|
|
92
|
+
)
|
|
91
93
|
|
|
92
94
|
event = NodeMutatedEvent(
|
|
93
95
|
branch=context.branch.name,
|
|
@@ -5,9 +5,13 @@ from graphql import GraphQLResolveInfo
|
|
|
5
5
|
|
|
6
6
|
from infrahub.core import registry
|
|
7
7
|
from infrahub.core.diff.coordinator import DiffCoordinator
|
|
8
|
+
from infrahub.core.diff.model.path import NameTrackingId
|
|
8
9
|
from infrahub.core.diff.models import RequestDiffUpdate
|
|
10
|
+
from infrahub.core.diff.repository.repository import DiffRepository
|
|
11
|
+
from infrahub.core.timestamp import Timestamp
|
|
9
12
|
from infrahub.database import retry_db_transaction
|
|
10
13
|
from infrahub.dependencies.registry import get_component_registry
|
|
14
|
+
from infrahub.exceptions import ValidationError
|
|
11
15
|
from infrahub.workflows.catalogue import DIFF_UPDATE
|
|
12
16
|
|
|
13
17
|
if TYPE_CHECKING:
|
|
@@ -40,11 +44,31 @@ class DiffUpdateMutation(Mutation):
|
|
|
40
44
|
|
|
41
45
|
from_timestamp_str = DateTime.serialize(data.from_time) if data.from_time else None
|
|
42
46
|
to_timestamp_str = DateTime.serialize(data.to_time) if data.to_time else None
|
|
43
|
-
if data.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
if (data.from_time or data.to_time) and not data.name:
|
|
48
|
+
raise ValidationError("diff with specified time range requires a name")
|
|
49
|
+
|
|
50
|
+
component_registry = get_component_registry()
|
|
51
|
+
base_branch = await registry.get_branch(db=context.db, branch=registry.default_branch)
|
|
52
|
+
diff_branch = await registry.get_branch(db=context.db, branch=data.branch)
|
|
53
|
+
diff_repository = await component_registry.get_component(DiffRepository, db=context.db, branch=diff_branch)
|
|
47
54
|
|
|
55
|
+
tracking_id = NameTrackingId(name=data.name)
|
|
56
|
+
existing_diffs_metatdatas = await diff_repository.get_roots_metadata(
|
|
57
|
+
diff_branch_names=[diff_branch.name], base_branch_names=[base_branch.name], tracking_id=tracking_id
|
|
58
|
+
)
|
|
59
|
+
if existing_diffs_metatdatas:
|
|
60
|
+
metadata = existing_diffs_metatdatas[0]
|
|
61
|
+
from_time = Timestamp(from_timestamp_str) if from_timestamp_str else None
|
|
62
|
+
to_time = Timestamp(to_timestamp_str) if to_timestamp_str else None
|
|
63
|
+
branched_from_timestamp = Timestamp(diff_branch.get_branched_from())
|
|
64
|
+
if from_time and from_time > metadata.from_time:
|
|
65
|
+
raise ValidationError(f"from_time must be null or less than or equal to {metadata.from_time}")
|
|
66
|
+
if from_time and from_time < branched_from_timestamp:
|
|
67
|
+
raise ValidationError(f"from_time must be null or greater than or equal to {branched_from_timestamp}")
|
|
68
|
+
if to_time and to_time < metadata.to_time:
|
|
69
|
+
raise ValidationError(f"to_time must be null or greater than or equal to {metadata.to_time}")
|
|
70
|
+
|
|
71
|
+
if data.wait_for_completion is True:
|
|
48
72
|
diff_coordinator = await component_registry.get_component(
|
|
49
73
|
DiffCoordinator, db=context.db, branch=diff_branch
|
|
50
74
|
)
|
|
@@ -97,7 +97,7 @@ class InfrahubMutationMixin:
|
|
|
97
97
|
log_data = get_log_data()
|
|
98
98
|
request_id = log_data.get("request_id", "")
|
|
99
99
|
|
|
100
|
-
graphql_payload = await obj.to_graphql(db=context.db, filter_sensitive=True)
|
|
100
|
+
graphql_payload = await obj.to_graphql(db=context.db, filter_sensitive=True, include_properties=False)
|
|
101
101
|
event = NodeMutatedEvent(
|
|
102
102
|
branch=context.branch.name,
|
|
103
103
|
kind=obj._schema.kind,
|
|
@@ -175,20 +175,25 @@ class InfrahubMutationMixin:
|
|
|
175
175
|
branch: Branch,
|
|
176
176
|
) -> Node:
|
|
177
177
|
component_registry = get_component_registry()
|
|
178
|
-
node_constraint_runner = await component_registry.get_component(
|
|
178
|
+
node_constraint_runner = await component_registry.get_component(
|
|
179
|
+
NodeConstraintRunner, db=db.start_session(), branch=branch
|
|
180
|
+
)
|
|
179
181
|
node_class = Node
|
|
180
182
|
if cls._meta.schema.kind in registry.node:
|
|
181
183
|
node_class = registry.node[cls._meta.schema.kind]
|
|
182
184
|
|
|
185
|
+
fields_to_validate = list(data)
|
|
183
186
|
try:
|
|
184
|
-
obj = await node_class.init(db=db, schema=cls._meta.schema, branch=branch)
|
|
185
|
-
await obj.new(db=db, **data)
|
|
186
|
-
fields_to_validate = list(data)
|
|
187
|
-
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
188
187
|
if db.is_transaction:
|
|
188
|
+
obj = await node_class.init(db=db, schema=cls._meta.schema, branch=branch)
|
|
189
|
+
await obj.new(db=db, **data)
|
|
190
|
+
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
189
191
|
await obj.save(db=db)
|
|
190
192
|
else:
|
|
191
193
|
async with db.start_transaction() as dbt:
|
|
194
|
+
obj = await node_class.init(db=dbt, schema=cls._meta.schema, branch=branch)
|
|
195
|
+
await obj.new(db=dbt, **data)
|
|
196
|
+
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
192
197
|
await obj.save(db=dbt)
|
|
193
198
|
|
|
194
199
|
except ValidationError as exc:
|
|
@@ -5,7 +5,8 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
from graphene import Boolean, InputField, InputObjectType, List, Mutation, String
|
|
6
6
|
from infrahub_sdk.utils import compare_lists
|
|
7
7
|
|
|
8
|
-
from infrahub.core.
|
|
8
|
+
from infrahub.core.account import GlobalPermission, ObjectPermission
|
|
9
|
+
from infrahub.core.constants import InfrahubKind, PermissionAction, PermissionDecision, RelationshipCardinality
|
|
9
10
|
from infrahub.core.manager import NodeManager
|
|
10
11
|
from infrahub.core.query.relationship import (
|
|
11
12
|
RelationshipGetPeerQuery,
|
|
@@ -14,6 +15,7 @@ from infrahub.core.query.relationship import (
|
|
|
14
15
|
from infrahub.core.relationship import Relationship
|
|
15
16
|
from infrahub.database import retry_db_transaction
|
|
16
17
|
from infrahub.exceptions import NodeNotFoundError, ValidationError
|
|
18
|
+
from infrahub.permissions import get_global_permission_for_kind
|
|
17
19
|
|
|
18
20
|
from ..types import RelatedNodeInput
|
|
19
21
|
|
|
@@ -76,6 +78,32 @@ class RelationshipMixin:
|
|
|
76
78
|
db=context.db, ids=node_ids, fields={"display_label": None}, branch=context.branch
|
|
77
79
|
)
|
|
78
80
|
|
|
81
|
+
if context.account_session:
|
|
82
|
+
impacted_schemas = {node.get_schema() for node in [source] + list(nodes.values())}
|
|
83
|
+
required_permissions: list[GlobalPermission | ObjectPermission] = []
|
|
84
|
+
decision = (
|
|
85
|
+
PermissionDecision.ALLOW_DEFAULT.value
|
|
86
|
+
if context.branch.is_default
|
|
87
|
+
else PermissionDecision.ALLOW_OTHER.value
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
for impacted_schema in impacted_schemas:
|
|
91
|
+
global_action = get_global_permission_for_kind(schema=impacted_schema)
|
|
92
|
+
|
|
93
|
+
if global_action:
|
|
94
|
+
required_permissions.append(GlobalPermission(action=global_action, decision=decision))
|
|
95
|
+
else:
|
|
96
|
+
required_permissions.append(
|
|
97
|
+
ObjectPermission(
|
|
98
|
+
namespace=impacted_schema.namespace,
|
|
99
|
+
name=impacted_schema.name,
|
|
100
|
+
action=PermissionAction.UPDATE.value,
|
|
101
|
+
decision=decision,
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
context.active_permissions.raise_for_permissions(permissions=required_permissions)
|
|
106
|
+
|
|
79
107
|
_, _, in_list2 = compare_lists(list1=list(nodes.keys()), list2=node_ids)
|
|
80
108
|
if in_list2:
|
|
81
109
|
for node_id in in_list2:
|
|
@@ -31,14 +31,17 @@ async def merge_branch_mutation(branch: str) -> None:
|
|
|
31
31
|
diff_coordinator = await component_registry.get_component(DiffCoordinator, db=db, branch=obj)
|
|
32
32
|
diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
|
|
33
33
|
diff_merger = await component_registry.get_component(DiffMerger, db=db, branch=obj)
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
enriched_diff_metadata = await diff_coordinator.update_branch_diff(base_branch=base_branch, diff_branch=obj)
|
|
35
|
+
async for _ in diff_repository.get_all_conflicts_for_diff(
|
|
36
|
+
diff_branch_name=enriched_diff_metadata.diff_branch_name, diff_id=enriched_diff_metadata.uuid
|
|
37
|
+
):
|
|
38
|
+
# if there are any conflicts, raise the error
|
|
36
39
|
raise ValidationError(
|
|
37
40
|
f"Branch {obj.name} contains conflicts with the default branch."
|
|
38
41
|
" Please create a Proposed Change to resolve the conflicts or manually update them before merging."
|
|
39
42
|
)
|
|
40
43
|
node_diff_field_summaries = await diff_repository.get_node_field_summaries(
|
|
41
|
-
diff_branch_name=
|
|
44
|
+
diff_branch_name=enriched_diff_metadata.diff_branch_name, diff_id=enriched_diff_metadata.uuid
|
|
42
45
|
)
|
|
43
46
|
|
|
44
47
|
merger = BranchMerger(
|
|
@@ -21,8 +21,10 @@ from infrahub.pools.number import NumberUtilizationGetter
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
22
|
from graphql import GraphQLResolveInfo
|
|
23
23
|
|
|
24
|
+
from infrahub.core.branch import Branch
|
|
24
25
|
from infrahub.core.node import Node
|
|
25
26
|
from infrahub.core.protocols import CoreNode
|
|
27
|
+
from infrahub.core.timestamp import Timestamp
|
|
26
28
|
from infrahub.database import InfrahubDatabase
|
|
27
29
|
from infrahub.graphql.initialization import GraphqlContext
|
|
28
30
|
|
|
@@ -184,7 +186,7 @@ class PoolUtilization(ObjectType):
|
|
|
184
186
|
pool: CoreNode | None = await NodeManager.get_one(id=pool_id, db=db, branch=context.branch)
|
|
185
187
|
pool = _validate_pool_type(pool_id=pool_id, pool=pool)
|
|
186
188
|
if pool.get_kind() == "CoreNumberPool":
|
|
187
|
-
return await resolve_number_pool_utilization(db=db,
|
|
189
|
+
return await resolve_number_pool_utilization(db=db, at=context.at, pool=pool, branch=context.branch)
|
|
188
190
|
|
|
189
191
|
resources_map: dict[str, Node] = {}
|
|
190
192
|
|
|
@@ -290,8 +292,10 @@ async def resolve_number_pool_allocation(
|
|
|
290
292
|
return response
|
|
291
293
|
|
|
292
294
|
|
|
293
|
-
async def resolve_number_pool_utilization(
|
|
294
|
-
|
|
295
|
+
async def resolve_number_pool_utilization(
|
|
296
|
+
db: InfrahubDatabase, pool: CoreNode, at: Timestamp | str | None, branch: Branch
|
|
297
|
+
) -> dict:
|
|
298
|
+
number_pool = NumberUtilizationGetter(db=db, pool=pool, at=at, branch=branch)
|
|
295
299
|
await number_pool.load_data()
|
|
296
300
|
|
|
297
301
|
return {
|
infrahub/permissions/__init__.py
CHANGED
|
@@ -2,12 +2,13 @@ from infrahub.permissions.backend import PermissionBackend
|
|
|
2
2
|
from infrahub.permissions.local_backend import LocalPermissionBackend
|
|
3
3
|
from infrahub.permissions.manager import PermissionManager
|
|
4
4
|
from infrahub.permissions.report import report_schema_permissions
|
|
5
|
-
from infrahub.permissions.types import AssignedPermissions
|
|
5
|
+
from infrahub.permissions.types import AssignedPermissions, get_global_permission_for_kind
|
|
6
6
|
|
|
7
7
|
__all__ = [
|
|
8
8
|
"AssignedPermissions",
|
|
9
9
|
"LocalPermissionBackend",
|
|
10
10
|
"PermissionBackend",
|
|
11
11
|
"PermissionManager",
|
|
12
|
+
"get_global_permission_for_kind",
|
|
12
13
|
"report_schema_permissions",
|
|
13
14
|
]
|
infrahub/permissions/types.py
CHANGED
|
@@ -2,8 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING, TypedDict
|
|
4
4
|
|
|
5
|
+
from infrahub.core.constants import GlobalPermissions, InfrahubKind
|
|
6
|
+
from infrahub.core.schema import NodeSchema
|
|
7
|
+
|
|
5
8
|
if TYPE_CHECKING:
|
|
6
9
|
from infrahub.core.account import GlobalPermission, ObjectPermission
|
|
10
|
+
from infrahub.core.schema import MainSchemaTypes
|
|
7
11
|
from infrahub.permissions.constants import BranchRelativePermissionDecision
|
|
8
12
|
|
|
9
13
|
|
|
@@ -18,3 +22,25 @@ class KindPermissions(TypedDict):
|
|
|
18
22
|
delete: BranchRelativePermissionDecision
|
|
19
23
|
update: BranchRelativePermissionDecision
|
|
20
24
|
view: BranchRelativePermissionDecision
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_global_permission_for_kind(schema: MainSchemaTypes) -> GlobalPermissions | None:
|
|
28
|
+
kind_permission_map = {
|
|
29
|
+
InfrahubKind.GENERICACCOUNT: GlobalPermissions.MANAGE_ACCOUNTS,
|
|
30
|
+
InfrahubKind.ACCOUNTGROUP: GlobalPermissions.MANAGE_ACCOUNTS,
|
|
31
|
+
InfrahubKind.ACCOUNTROLE: GlobalPermissions.MANAGE_ACCOUNTS,
|
|
32
|
+
InfrahubKind.BASEPERMISSION: GlobalPermissions.MANAGE_PERMISSIONS,
|
|
33
|
+
InfrahubKind.GENERICREPOSITORY: GlobalPermissions.MANAGE_REPOSITORIES,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if schema.kind in kind_permission_map:
|
|
37
|
+
return kind_permission_map[schema.kind]
|
|
38
|
+
|
|
39
|
+
if isinstance(schema, NodeSchema):
|
|
40
|
+
for base in schema.inherit_from:
|
|
41
|
+
try:
|
|
42
|
+
return kind_permission_map[base]
|
|
43
|
+
except KeyError:
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
return None
|
infrahub_sdk/batch.py
CHANGED
|
@@ -30,7 +30,7 @@ class BatchTaskSync:
|
|
|
30
30
|
result = None
|
|
31
31
|
try:
|
|
32
32
|
result = self.task(*self.args, **self.kwargs)
|
|
33
|
-
except Exception as exc:
|
|
33
|
+
except Exception as exc: # pylint: disable=broad-exception-caught
|
|
34
34
|
if return_exceptions:
|
|
35
35
|
return self.node, exc
|
|
36
36
|
raise exc
|
|
@@ -44,7 +44,7 @@ async def execute_batch_task_in_pool(
|
|
|
44
44
|
async with semaphore:
|
|
45
45
|
try:
|
|
46
46
|
result = await task.task(*task.args, **task.kwargs)
|
|
47
|
-
except Exception as exc:
|
|
47
|
+
except Exception as exc: # pylint: disable=broad-exception-caught
|
|
48
48
|
if return_exceptions:
|
|
49
49
|
return (task.node, exc)
|
|
50
50
|
raise exc
|
infrahub_sdk/config.py
CHANGED
|
@@ -113,7 +113,7 @@ class ConfigBase(BaseSettings):
|
|
|
113
113
|
|
|
114
114
|
@model_validator(mode="after")
|
|
115
115
|
def validate_proxy_config(self) -> Self:
|
|
116
|
-
if self.proxy and self.proxy_mounts.is_set:
|
|
116
|
+
if self.proxy and self.proxy_mounts.is_set: # pylint: disable=no-member
|
|
117
117
|
raise ValueError("'proxy' and 'proxy_mounts' are mutually exclusive")
|
|
118
118
|
return self
|
|
119
119
|
|
infrahub_sdk/ctl/check.py
CHANGED
|
@@ -121,7 +121,7 @@ async def run_check(
|
|
|
121
121
|
except QueryNotFoundError as exc:
|
|
122
122
|
log.warning(f"{module_name}::{check}: unable to find query ({exc!s})")
|
|
123
123
|
passed = False
|
|
124
|
-
except Exception as exc:
|
|
124
|
+
except Exception as exc: # pylint: disable=broad-exception-caught
|
|
125
125
|
log.warning(f"{module_name}::{check}: An error occurred during execution ({exc})")
|
|
126
126
|
passed = False
|
|
127
127
|
|
infrahub_sdk/ctl/utils.py
CHANGED
|
@@ -88,7 +88,7 @@ def catch_exception(
|
|
|
88
88
|
async def async_wrapper(*args: Any, **kwargs: Any) -> T:
|
|
89
89
|
try:
|
|
90
90
|
return await func(*args, **kwargs)
|
|
91
|
-
except (Error, Exception) as exc:
|
|
91
|
+
except (Error, Exception) as exc: # pylint: disable=broad-exception-caught
|
|
92
92
|
return handle_exception(exc=exc, console=console, exit_code=exit_code)
|
|
93
93
|
|
|
94
94
|
return async_wrapper
|
|
@@ -97,7 +97,7 @@ def catch_exception(
|
|
|
97
97
|
def wrapper(*args: Any, **kwargs: Any) -> T:
|
|
98
98
|
try:
|
|
99
99
|
return func(*args, **kwargs)
|
|
100
|
-
except (Error, Exception) as exc:
|
|
100
|
+
except (Error, Exception) as exc: # pylint: disable=broad-exception-caught
|
|
101
101
|
return handle_exception(exc=exc, console=console, exit_code=exit_code)
|
|
102
102
|
|
|
103
103
|
return wrapper
|
infrahub_sdk/data.py
CHANGED
|
@@ -20,7 +20,7 @@ class RepositoryData(BaseModel):
|
|
|
20
20
|
branch_info: dict[str, RepositoryBranchInfo] = Field(default_factory=dict)
|
|
21
21
|
|
|
22
22
|
def get_staging_branch(self) -> str | None:
|
|
23
|
-
for branch, info in self.branch_info.items():
|
|
23
|
+
for branch, info in self.branch_info.items(): # pylint: disable=no-member
|
|
24
24
|
if info.internal_status == "staging":
|
|
25
25
|
return branch
|
|
26
26
|
return None
|
infrahub_sdk/node.py
CHANGED
|
@@ -25,6 +25,7 @@ if TYPE_CHECKING:
|
|
|
25
25
|
from .schema import AttributeSchemaAPI, MainSchemaTypesAPI, RelationshipSchemaAPI
|
|
26
26
|
from .types import Order
|
|
27
27
|
|
|
28
|
+
# pylint: disable=too-many-lines
|
|
28
29
|
|
|
29
30
|
PROPERTIES_FLAG = ["is_visible", "is_protected"]
|
|
30
31
|
PROPERTIES_OBJECT = ["source", "owner"]
|
|
@@ -800,7 +801,7 @@ class InfrahubNodeBase:
|
|
|
800
801
|
Returns:
|
|
801
802
|
dict[str, Dict]: Representation of an input data in dict format
|
|
802
803
|
"""
|
|
803
|
-
|
|
804
|
+
# pylint: disable=too-many-branches
|
|
804
805
|
data = {}
|
|
805
806
|
variables = {}
|
|
806
807
|
|
|
@@ -1250,6 +1251,7 @@ class InfrahubNode(InfrahubNodeBase):
|
|
|
1250
1251
|
Returns:
|
|
1251
1252
|
dict[str, Union[Any, Dict]]: GraphQL query in dictionary format
|
|
1252
1253
|
"""
|
|
1254
|
+
# pylint: disable=too-many-branches
|
|
1253
1255
|
|
|
1254
1256
|
data: dict[str, Any] = {}
|
|
1255
1257
|
|
|
@@ -1761,6 +1763,7 @@ class InfrahubNodeSync(InfrahubNodeBase):
|
|
|
1761
1763
|
Returns:
|
|
1762
1764
|
dict[str, Union[Any, Dict]]: GraphQL query in dictionary format
|
|
1763
1765
|
"""
|
|
1766
|
+
# pylint: disable=too-many-branches
|
|
1764
1767
|
|
|
1765
1768
|
data: dict[str, Any] = {}
|
|
1766
1769
|
|
infrahub_sdk/protocols.py
CHANGED
infrahub_sdk/schema/__init__.py
CHANGED
infrahub_sdk/testing/docker.py
CHANGED
|
@@ -1,40 +1,10 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
1
|
import pytest
|
|
6
2
|
from infrahub_testcontainers.helpers import TestInfrahubDocker
|
|
7
|
-
from packaging.version import InvalidVersion, Version
|
|
8
3
|
|
|
9
4
|
from .. import Config, InfrahubClient, InfrahubClientSync
|
|
10
5
|
|
|
11
|
-
INFRAHUB_VERSION = os.getenv("INFRAHUB_TESTING_IMAGE_VER", "latest")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def skip_version(min_infrahub_version: str | None = None, max_infrahub_version: str | None = None) -> bool:
|
|
15
|
-
"""
|
|
16
|
-
Check if a test should be skipped depending on infrahub version.
|
|
17
|
-
"""
|
|
18
|
-
try:
|
|
19
|
-
version = Version(INFRAHUB_VERSION)
|
|
20
|
-
except InvalidVersion:
|
|
21
|
-
# We would typically end up here for development purpose while running a CI test against
|
|
22
|
-
# unreleased versions of infrahub, like `stable` or `develop` branch.
|
|
23
|
-
# For now, we consider this means we are testing against the most recent version of infrahub,
|
|
24
|
-
# so we skip if the test should not be ran against a maximum version.
|
|
25
|
-
return max_infrahub_version is None
|
|
26
|
-
|
|
27
|
-
if min_infrahub_version is not None and version < Version(min_infrahub_version):
|
|
28
|
-
return True
|
|
29
|
-
|
|
30
|
-
return max_infrahub_version is not None and version > Version(max_infrahub_version)
|
|
31
|
-
|
|
32
6
|
|
|
33
7
|
class TestInfrahubDockerClient(TestInfrahubDocker):
|
|
34
|
-
@pytest.fixture(scope="class")
|
|
35
|
-
def infrahub_version(self) -> str:
|
|
36
|
-
return INFRAHUB_VERSION
|
|
37
|
-
|
|
38
8
|
@pytest.fixture(scope="class")
|
|
39
9
|
def client(self, infrahub_port: int) -> InfrahubClient:
|
|
40
10
|
return InfrahubClient(
|
|
@@ -98,7 +98,7 @@ class LineDelimitedJSONExporter(ExporterInterface):
|
|
|
98
98
|
return many_relationships
|
|
99
99
|
|
|
100
100
|
# FIXME: Split in smaller functions
|
|
101
|
-
async def export(
|
|
101
|
+
async def export( # pylint: disable=too-many-branches
|
|
102
102
|
self, export_directory: Path, namespaces: list[str], branch: str, exclude: list[str] | None = None
|
|
103
103
|
) -> None:
|
|
104
104
|
illegal_namespaces = set(ILLEGAL_NAMESPACES)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: infrahub-server
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.7
|
|
4
4
|
Summary: Infrahub is taking a new approach to Infrastructure Management by providing a new generation of datastore to organize and control all the data that defines how an infrastructure should run.
|
|
5
5
|
Home-page: https://opsmill.com
|
|
6
6
|
License: AGPL-3.0-only
|
|
@@ -58,16 +58,46 @@ Project-URL: Documentation, https://docs.infrahub.app/
|
|
|
58
58
|
Project-URL: Repository, https://github.com/opsmill/infrahub
|
|
59
59
|
Description-Content-Type: text/markdown
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
<h1 align="center">
|
|
62
|
+
<a href=""><img src="docs/static/img/infrahub-hori.svg" alt="Infrahub" width="350"></a>
|
|
63
|
+
</h1>
|
|
64
|
+
<h3 align="center">Simplify Infrastructure Automation</h2>
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
<p align="center">
|
|
67
|
+
<a href="https://www.linkedin.com/company/opsmill">
|
|
68
|
+
<img src="https://img.shields.io/badge/linkedin-blue?logo=linkedin"/>
|
|
69
|
+
</a>
|
|
70
|
+
<a href="https://discord.gg/opsmill">
|
|
71
|
+
<img src="https://img.shields.io/badge/Discord-7289DA?&logo=discord&logoColor=white"/>
|
|
72
|
+
</a>
|
|
73
|
+
</p>
|
|
66
74
|
|
|
67
|
-
Infrahub from [OpsMill](https://opsmill.com) is taking a new approach to Infrastructure Management by providing a new generation of datastore to organize and control all the data that defines how an infrastructure should run. Infrahub offers a central hub to manage the data, templates and playbooks that powers your infrastructure by combining the version control and branch management capabilities
|
|
75
|
+
Infrahub from [OpsMill](https://opsmill.com) is taking a new approach to Infrastructure Management by providing a new generation of datastore to organize and control all the data that defines how an infrastructure should run. Infrahub offers a central hub to manage the data, templates and playbooks that powers your infrastructure by combining the version control and branch management capabilities similar to Git with the flexible data model and UI of a graph database.
|
|
76
|
+
|
|
77
|
+
If you just want to try Infrahub out, you can use our [Always-On Sandbox](https://demo.infrahub.app/) to get started.
|
|
68
78
|
|
|
69
79
|

|
|
70
80
|
|
|
81
|
+
## Why Use Infrahub?
|
|
82
|
+
|
|
83
|
+
**Unified Source of Truth** - Infrahub is a single source of truth for all your infrastructure and network data. It provides a unified view of your infrastructure, allowing you to manage your infrastructure in a more efficient and effective way. Infrahub allows unidirectional and bi-directional [data synchronization](https://docs.infrahub.app/sync/sync/) between other internal systems and Infrahub. The data can be accessed via WebUI, API and SDK, along with SSO and RBAC for access control.
|
|
84
|
+
|
|
85
|
+
**Flexible Schema** - Infrahub provides a flexible schema for your infrastructure data and related business information, allowing you to define your own data model and customize it to your needs. Get started quickly with our [schema library](https://github.com/opsmill/schema-library) or build your own.
|
|
86
|
+
|
|
87
|
+
**Version Control** - Infrahub provides a version control system for your infrastructure data, allowing you to track changes and revert to previous versions if needed. Immutable history of all changes to the data and artifacts is maintained, allowing you to audit and review changes to your infrastructure.
|
|
88
|
+
|
|
89
|
+
**CI Pipeline and Validation** - Infrahub provides a CI pipeline and validation system for your infrastructure data, allowing you to ensure that your infrastructure is always in a valid state. Infrahub was designed with infrastructure-as-code workflows in mind, removing fragility and complexity of combining together multiple tools and projects to achieve the same goal.
|
|
90
|
+
|
|
91
|
+
## Infrahub Use Cases
|
|
92
|
+
|
|
93
|
+
**Service Catalog** - Infrahub acts as the underlying system to provide infrastructure-as-a-service, allowing you to manage your services and lifecycle them as the services evolve.
|
|
94
|
+
|
|
95
|
+
**Infrastructure Automation** - Provide infrastructure and network automation workflows with Infrahub rendering configurations and artifacts via Jinja2 and python,then passing to deployment tools such as [Nornir](https://www.opsmill.com/simplifying-network-automation-workflows-with-infrahub-nornir-and-jinja2/), [Ansible](https://docs.infrahub.app/ansible/ansible/), Terraform, or vendor-specific tools.
|
|
96
|
+
|
|
97
|
+
**Inventory Management** - Infrahub serves as a centralized inventory system for your infrastructure, allowing you to manage your inventory and track changes to your infrastructure. It provides a WebUI and API for other teams to self-service the information needed to allow the organization to operate.
|
|
98
|
+
|
|
99
|
+
**DCIM and IPAM** - Infrahub provides centralized DCIM and IPAM systems for your infrastructure, capable of handling complex cases such as overlapping IP addresses and VLANs, automation-friendly, branch-aware allocation of resources via Infrahub's [Resource Manager](https://docs.infrahub.app/python-sdk/guides/resource-manager), and more.
|
|
100
|
+
|
|
71
101
|
## Quick Start
|
|
72
102
|
|
|
73
103
|
[Always-On Sandbox](https://demo.infrahub.app/) - Instantly login to the UI of a demo environment of Infrahub with sample data pre-loaded.
|
|
@@ -94,7 +124,11 @@ If you need help, support for the community version of Infrahub is provided on [
|
|
|
94
124
|
|
|
95
125
|
## Contributing
|
|
96
126
|
|
|
97
|
-
|
|
127
|
+
To help our community with the creation of contributions, please view our [CONTRIBUTING](./CONTRIBUTING.md) page.
|
|
128
|
+
|
|
129
|
+
<a href="https://github.com/opsmill/infrahub/graphs/contributors">
|
|
130
|
+
<img src="https://contrib.rocks/image?repo=opsmill/infrahub" />
|
|
131
|
+
</a>
|
|
98
132
|
|
|
99
133
|
## Security
|
|
100
134
|
|