infrahub-server 1.1.3__py3-none-any.whl → 1.1.5__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 +4 -1
- infrahub/api/oidc.py +32 -4
- infrahub/api/schema.py +16 -3
- infrahub/api/transformation.py +2 -0
- infrahub/computed_attribute/tasks.py +9 -5
- infrahub/config.py +0 -1
- infrahub/core/constants/__init__.py +5 -0
- infrahub/core/diff/calculator.py +118 -8
- infrahub/core/diff/coordinator.py +1 -2
- infrahub/core/diff/model/path.py +0 -9
- infrahub/core/diff/query/all_conflicts.py +64 -0
- infrahub/core/diff/query_parser.py +51 -28
- infrahub/core/diff/repository/repository.py +23 -14
- infrahub/core/merge.py +7 -5
- infrahub/core/query/diff.py +417 -621
- infrahub/core/relationship/model.py +10 -2
- infrahub/core/schema/__init__.py +5 -0
- infrahub/core/validators/aggregated_checker.py +34 -4
- infrahub/core/validators/node/hierarchy.py +1 -1
- infrahub/generators/tasks.py +12 -10
- infrahub/git/base.py +50 -8
- infrahub/git/integrator.py +24 -17
- infrahub/git/models.py +3 -2
- infrahub/git/repository.py +2 -2
- infrahub/git/tasks.py +19 -11
- infrahub/graphql/mutations/artifact_definition.py +10 -2
- infrahub/message_bus/messages/check_repository_usercheck.py +1 -0
- infrahub/message_bus/operations/check/repository.py +5 -2
- infrahub/message_bus/operations/requests/artifact_definition.py +1 -1
- infrahub/message_bus/operations/requests/proposed_change.py +4 -0
- infrahub/message_bus/types.py +1 -0
- infrahub/transformations/constants.py +1 -0
- infrahub/transformations/models.py +3 -1
- infrahub/transformations/tasks.py +2 -2
- infrahub/webhook/models.py +9 -1
- infrahub/workflows/catalogue.py +2 -2
- infrahub_sdk/analyzer.py +1 -1
- infrahub_sdk/checks.py +4 -4
- infrahub_sdk/client.py +26 -16
- infrahub_sdk/ctl/cli_commands.py +4 -4
- infrahub_sdk/ctl/exporter.py +2 -2
- infrahub_sdk/ctl/importer.py +6 -4
- infrahub_sdk/ctl/repository.py +56 -1
- infrahub_sdk/generator.py +3 -3
- infrahub_sdk/node.py +2 -2
- infrahub_sdk/pytest_plugin/items/base.py +0 -5
- infrahub_sdk/pytest_plugin/items/graphql_query.py +1 -1
- infrahub_sdk/pytest_plugin/items/jinja2_transform.py +1 -1
- infrahub_sdk/pytest_plugin/items/python_transform.py +1 -1
- infrahub_sdk/repository.py +33 -0
- infrahub_sdk/testing/repository.py +14 -8
- infrahub_sdk/transforms.py +3 -3
- infrahub_sdk/utils.py +8 -3
- {infrahub_server-1.1.3.dist-info → infrahub_server-1.1.5.dist-info}/METADATA +2 -1
- {infrahub_server-1.1.3.dist-info → infrahub_server-1.1.5.dist-info}/RECORD +59 -57
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_sdk/task_report.py +0 -208
- {infrahub_server-1.1.3.dist-info → infrahub_server-1.1.5.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.3.dist-info → infrahub_server-1.1.5.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.3.dist-info → infrahub_server-1.1.5.dist-info}/entry_points.txt +0 -0
|
@@ -10,7 +10,8 @@ class TransformPythonData(BaseModel):
|
|
|
10
10
|
data: dict = Field(..., description="Input data for the template")
|
|
11
11
|
branch: str = Field(..., description="The branch to target")
|
|
12
12
|
transform_location: str = Field(..., description="Location of the transform within the repository")
|
|
13
|
-
commit: str = Field(..., description="The commit id to use when
|
|
13
|
+
commit: str = Field(..., description="The commit id to use when generating the artifact")
|
|
14
|
+
timeout: int = Field(..., description="The timeout value to use when generating the artifact")
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class TransformJinjaTemplateData(BaseModel):
|
|
@@ -23,3 +24,4 @@ class TransformJinjaTemplateData(BaseModel):
|
|
|
23
24
|
branch: str = Field(..., description="The branch to target")
|
|
24
25
|
template_location: str = Field(..., description="Location of the template within the repository")
|
|
25
26
|
commit: str = Field(..., description="The commit id to use when rendering the template")
|
|
27
|
+
timeout: int = Field(..., description="The timeout value to use when rendering the template")
|
|
@@ -25,7 +25,7 @@ async def transform_python(message: TransformPythonData) -> Any:
|
|
|
25
25
|
commit=message.commit,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
transformed_data = await repo.execute_python_transform(
|
|
28
|
+
transformed_data = await repo.execute_python_transform.with_options(timeout_seconds=message.timeout)(
|
|
29
29
|
branch_name=message.branch,
|
|
30
30
|
commit=message.commit,
|
|
31
31
|
location=message.transform_location,
|
|
@@ -49,7 +49,7 @@ async def transform_render_jinja2_template(message: TransformJinjaTemplateData)
|
|
|
49
49
|
commit=message.commit,
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
-
rendered_template = await repo.render_jinja2_template(
|
|
52
|
+
rendered_template = await repo.render_jinja2_template.with_options(timeout_seconds=message.timeout)(
|
|
53
53
|
commit=message.commit, location=message.template_location, data={"data": message.data}
|
|
54
54
|
)
|
|
55
55
|
|
infrahub/webhook/models.py
CHANGED
|
@@ -6,11 +6,13 @@ from math import floor
|
|
|
6
6
|
from typing import Any, Optional, Union
|
|
7
7
|
from uuid import uuid4
|
|
8
8
|
|
|
9
|
+
from infrahub_sdk.protocols import CoreTransformPython
|
|
9
10
|
from pydantic import BaseModel, ConfigDict, Field
|
|
10
11
|
|
|
11
12
|
from infrahub.core.constants import InfrahubKind
|
|
12
13
|
from infrahub.git.repository import InfrahubReadOnlyRepository, InfrahubRepository
|
|
13
14
|
from infrahub.services import InfrahubServices
|
|
15
|
+
from infrahub.transformations.constants import DEFAULT_TRANSFORM_TIMEOUT
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class SendWebhookData(BaseModel):
|
|
@@ -95,7 +97,13 @@ class TransformWebhook(Webhook):
|
|
|
95
97
|
default_branch = repo.default_branch
|
|
96
98
|
commit = repo.get_commit_value(branch_name=default_branch)
|
|
97
99
|
|
|
98
|
-
|
|
100
|
+
timeout = DEFAULT_TRANSFORM_TIMEOUT
|
|
101
|
+
if transform := await self.service.client.get(
|
|
102
|
+
kind=CoreTransformPython, name__value=self.transform_name, raise_when_missing=False
|
|
103
|
+
):
|
|
104
|
+
timeout = transform.timeout.value
|
|
105
|
+
|
|
106
|
+
self._payload = await repo.execute_python_transform.with_options(timeout_seconds=timeout)(
|
|
99
107
|
branch_name=default_branch,
|
|
100
108
|
commit=commit,
|
|
101
109
|
location=f"{self.transform_file}::{self.transform_class}",
|
infrahub/workflows/catalogue.py
CHANGED
|
@@ -57,7 +57,7 @@ TRIGGER_ARTIFACT_DEFINITION_GENERATE = WorkflowDefinition(
|
|
|
57
57
|
)
|
|
58
58
|
|
|
59
59
|
TRIGGER_GENERATOR_DEFINITION_RUN = WorkflowDefinition(
|
|
60
|
-
name="
|
|
60
|
+
name="generator-definition-run",
|
|
61
61
|
type=WorkflowType.CORE,
|
|
62
62
|
module="infrahub.generators.tasks",
|
|
63
63
|
function="run_generator_definition",
|
|
@@ -81,7 +81,7 @@ REQUEST_GENERATOR_RUN = WorkflowDefinition(
|
|
|
81
81
|
)
|
|
82
82
|
|
|
83
83
|
REQUEST_GENERATOR_DEFINITION_RUN = WorkflowDefinition(
|
|
84
|
-
name="
|
|
84
|
+
name="request-generator-definition-run",
|
|
85
85
|
type=WorkflowType.CORE,
|
|
86
86
|
module="infrahub.generators.tasks",
|
|
87
87
|
function="request_generator_definition_run",
|
infrahub_sdk/analyzer.py
CHANGED
|
@@ -91,7 +91,7 @@ class GraphQLQueryAnalyzer:
|
|
|
91
91
|
else:
|
|
92
92
|
data["default_value"] = variable.default_value.value
|
|
93
93
|
|
|
94
|
-
if not data.get("default_value"
|
|
94
|
+
if not data.get("default_value") and non_null:
|
|
95
95
|
data["required"] = True
|
|
96
96
|
|
|
97
97
|
response.append(GraphQLQueryVariable(**data))
|
infrahub_sdk/checks.py
CHANGED
|
@@ -8,9 +8,10 @@ from abc import abstractmethod
|
|
|
8
8
|
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
10
10
|
import ujson
|
|
11
|
-
from git.repo import Repo
|
|
12
11
|
from pydantic import BaseModel, Field
|
|
13
12
|
|
|
13
|
+
from infrahub_sdk.repository import GitRepoManager
|
|
14
|
+
|
|
14
15
|
from .exceptions import UninitializedError
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
@@ -43,7 +44,7 @@ class InfrahubCheck:
|
|
|
43
44
|
params: dict | None = None,
|
|
44
45
|
client: InfrahubClient | None = None,
|
|
45
46
|
):
|
|
46
|
-
self.git:
|
|
47
|
+
self.git: GitRepoManager | None = None
|
|
47
48
|
self.initializer = initializer or InfrahubCheckInitializer()
|
|
48
49
|
|
|
49
50
|
self.logs: list[dict[str, Any]] = []
|
|
@@ -137,10 +138,9 @@ class InfrahubCheck:
|
|
|
137
138
|
return self.branch
|
|
138
139
|
|
|
139
140
|
if not self.git:
|
|
140
|
-
self.git =
|
|
141
|
+
self.git = GitRepoManager(self.root_directory)
|
|
141
142
|
|
|
142
143
|
self.branch = str(self.git.active_branch)
|
|
143
|
-
|
|
144
144
|
return self.branch
|
|
145
145
|
|
|
146
146
|
@abstractmethod
|
infrahub_sdk/client.py
CHANGED
|
@@ -547,8 +547,10 @@ class InfrahubClient(BaseClient):
|
|
|
547
547
|
at: Timestamp | None = None,
|
|
548
548
|
branch: str | None = None,
|
|
549
549
|
timeout: int | None = None,
|
|
550
|
+
**kwargs: Any,
|
|
550
551
|
) -> int:
|
|
551
552
|
"""Return the number of nodes of a given kind."""
|
|
553
|
+
filters = kwargs
|
|
552
554
|
schema = await self.schema.get(kind=kind, branch=branch)
|
|
553
555
|
|
|
554
556
|
branch = branch or self.default_branch
|
|
@@ -556,7 +558,10 @@ class InfrahubClient(BaseClient):
|
|
|
556
558
|
at = Timestamp(at)
|
|
557
559
|
|
|
558
560
|
response = await self.execute_graphql(
|
|
559
|
-
query=Query(query={schema.kind: {"count": None}}).render(),
|
|
561
|
+
query=Query(query={schema.kind: {"count": None, "@filters": filters}}).render(),
|
|
562
|
+
branch_name=branch,
|
|
563
|
+
at=at,
|
|
564
|
+
timeout=timeout,
|
|
560
565
|
)
|
|
561
566
|
return int(response.get(schema.kind, {}).get("count", 0))
|
|
562
567
|
|
|
@@ -781,7 +786,7 @@ class InfrahubClient(BaseClient):
|
|
|
781
786
|
nodes = []
|
|
782
787
|
related_nodes = []
|
|
783
788
|
batch_process = await self.create_batch()
|
|
784
|
-
count = await self.count(kind=schema.kind)
|
|
789
|
+
count = await self.count(kind=schema.kind, **filters)
|
|
785
790
|
total_pages = (count + pagination_size - 1) // pagination_size
|
|
786
791
|
|
|
787
792
|
for page_number in range(1, total_pages + 1):
|
|
@@ -1181,7 +1186,7 @@ class InfrahubClient(BaseClient):
|
|
|
1181
1186
|
async def allocate_next_ip_address(
|
|
1182
1187
|
self,
|
|
1183
1188
|
resource_pool: CoreNode,
|
|
1184
|
-
kind:
|
|
1189
|
+
kind: None = ...,
|
|
1185
1190
|
identifier: str | None = ...,
|
|
1186
1191
|
prefix_length: int | None = ...,
|
|
1187
1192
|
address_type: str | None = ...,
|
|
@@ -1196,7 +1201,7 @@ class InfrahubClient(BaseClient):
|
|
|
1196
1201
|
async def allocate_next_ip_address(
|
|
1197
1202
|
self,
|
|
1198
1203
|
resource_pool: CoreNode,
|
|
1199
|
-
kind:
|
|
1204
|
+
kind: None = ...,
|
|
1200
1205
|
identifier: str | None = ...,
|
|
1201
1206
|
prefix_length: int | None = ...,
|
|
1202
1207
|
address_type: str | None = ...,
|
|
@@ -1211,7 +1216,7 @@ class InfrahubClient(BaseClient):
|
|
|
1211
1216
|
async def allocate_next_ip_address(
|
|
1212
1217
|
self,
|
|
1213
1218
|
resource_pool: CoreNode,
|
|
1214
|
-
kind:
|
|
1219
|
+
kind: None = ...,
|
|
1215
1220
|
identifier: str | None = ...,
|
|
1216
1221
|
prefix_length: int | None = ...,
|
|
1217
1222
|
address_type: str | None = ...,
|
|
@@ -1328,7 +1333,7 @@ class InfrahubClient(BaseClient):
|
|
|
1328
1333
|
async def allocate_next_ip_prefix(
|
|
1329
1334
|
self,
|
|
1330
1335
|
resource_pool: CoreNode,
|
|
1331
|
-
kind:
|
|
1336
|
+
kind: None = ...,
|
|
1332
1337
|
identifier: str | None = ...,
|
|
1333
1338
|
prefix_length: int | None = ...,
|
|
1334
1339
|
member_type: str | None = ...,
|
|
@@ -1344,7 +1349,7 @@ class InfrahubClient(BaseClient):
|
|
|
1344
1349
|
async def allocate_next_ip_prefix(
|
|
1345
1350
|
self,
|
|
1346
1351
|
resource_pool: CoreNode,
|
|
1347
|
-
kind:
|
|
1352
|
+
kind: None = ...,
|
|
1348
1353
|
identifier: str | None = ...,
|
|
1349
1354
|
prefix_length: int | None = ...,
|
|
1350
1355
|
member_type: str | None = ...,
|
|
@@ -1360,7 +1365,7 @@ class InfrahubClient(BaseClient):
|
|
|
1360
1365
|
async def allocate_next_ip_prefix(
|
|
1361
1366
|
self,
|
|
1362
1367
|
resource_pool: CoreNode,
|
|
1363
|
-
kind:
|
|
1368
|
+
kind: None = ...,
|
|
1364
1369
|
identifier: str | None = ...,
|
|
1365
1370
|
prefix_length: int | None = ...,
|
|
1366
1371
|
member_type: str | None = ...,
|
|
@@ -1651,8 +1656,10 @@ class InfrahubClientSync(BaseClient):
|
|
|
1651
1656
|
at: Timestamp | None = None,
|
|
1652
1657
|
branch: str | None = None,
|
|
1653
1658
|
timeout: int | None = None,
|
|
1659
|
+
**kwargs: Any,
|
|
1654
1660
|
) -> int:
|
|
1655
1661
|
"""Return the number of nodes of a given kind."""
|
|
1662
|
+
filters = kwargs
|
|
1656
1663
|
schema = self.schema.get(kind=kind, branch=branch)
|
|
1657
1664
|
|
|
1658
1665
|
branch = branch or self.default_branch
|
|
@@ -1660,7 +1667,10 @@ class InfrahubClientSync(BaseClient):
|
|
|
1660
1667
|
at = Timestamp(at)
|
|
1661
1668
|
|
|
1662
1669
|
response = self.execute_graphql(
|
|
1663
|
-
query=Query(query={schema.kind: {"count": None}}).render(),
|
|
1670
|
+
query=Query(query={schema.kind: {"count": None, "@filters": filters}}).render(),
|
|
1671
|
+
branch_name=branch,
|
|
1672
|
+
at=at,
|
|
1673
|
+
timeout=timeout,
|
|
1664
1674
|
)
|
|
1665
1675
|
return int(response.get(schema.kind, {}).get("count", 0))
|
|
1666
1676
|
|
|
@@ -1920,7 +1930,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
1920
1930
|
related_nodes = []
|
|
1921
1931
|
batch_process = self.create_batch()
|
|
1922
1932
|
|
|
1923
|
-
count = self.count(kind=schema.kind)
|
|
1933
|
+
count = self.count(kind=schema.kind, **filters)
|
|
1924
1934
|
total_pages = (count + pagination_size - 1) // pagination_size
|
|
1925
1935
|
|
|
1926
1936
|
for page_number in range(1, total_pages + 1):
|
|
@@ -2296,7 +2306,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
2296
2306
|
def allocate_next_ip_address(
|
|
2297
2307
|
self,
|
|
2298
2308
|
resource_pool: CoreNodeSync,
|
|
2299
|
-
kind:
|
|
2309
|
+
kind: None = ...,
|
|
2300
2310
|
identifier: str | None = ...,
|
|
2301
2311
|
prefix_length: int | None = ...,
|
|
2302
2312
|
address_type: str | None = ...,
|
|
@@ -2311,7 +2321,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
2311
2321
|
def allocate_next_ip_address(
|
|
2312
2322
|
self,
|
|
2313
2323
|
resource_pool: CoreNodeSync,
|
|
2314
|
-
kind:
|
|
2324
|
+
kind: None = ...,
|
|
2315
2325
|
identifier: str | None = ...,
|
|
2316
2326
|
prefix_length: int | None = ...,
|
|
2317
2327
|
address_type: str | None = ...,
|
|
@@ -2326,7 +2336,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
2326
2336
|
def allocate_next_ip_address(
|
|
2327
2337
|
self,
|
|
2328
2338
|
resource_pool: CoreNodeSync,
|
|
2329
|
-
kind:
|
|
2339
|
+
kind: None = ...,
|
|
2330
2340
|
identifier: str | None = ...,
|
|
2331
2341
|
prefix_length: int | None = ...,
|
|
2332
2342
|
address_type: str | None = ...,
|
|
@@ -2439,7 +2449,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
2439
2449
|
def allocate_next_ip_prefix(
|
|
2440
2450
|
self,
|
|
2441
2451
|
resource_pool: CoreNodeSync,
|
|
2442
|
-
kind:
|
|
2452
|
+
kind: None = ...,
|
|
2443
2453
|
identifier: str | None = ...,
|
|
2444
2454
|
prefix_length: int | None = ...,
|
|
2445
2455
|
member_type: str | None = ...,
|
|
@@ -2455,7 +2465,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
2455
2465
|
def allocate_next_ip_prefix(
|
|
2456
2466
|
self,
|
|
2457
2467
|
resource_pool: CoreNodeSync,
|
|
2458
|
-
kind:
|
|
2468
|
+
kind: None = ...,
|
|
2459
2469
|
identifier: str | None = ...,
|
|
2460
2470
|
prefix_length: int | None = ...,
|
|
2461
2471
|
member_type: str | None = ...,
|
|
@@ -2471,7 +2481,7 @@ class InfrahubClientSync(BaseClient):
|
|
|
2471
2481
|
def allocate_next_ip_prefix(
|
|
2472
2482
|
self,
|
|
2473
2483
|
resource_pool: CoreNodeSync,
|
|
2474
|
-
kind:
|
|
2484
|
+
kind: None = ...,
|
|
2475
2485
|
identifier: str | None = ...,
|
|
2476
2486
|
prefix_length: int | None = ...,
|
|
2477
2487
|
member_type: str | None = ...,
|
infrahub_sdk/ctl/cli_commands.py
CHANGED
|
@@ -130,12 +130,12 @@ async def run(
|
|
|
130
130
|
debug: bool = False,
|
|
131
131
|
_: str = CONFIG_PARAM,
|
|
132
132
|
branch: str = typer.Option("main", help="Branch on which to run the script."),
|
|
133
|
-
concurrent: int = typer.Option(
|
|
134
|
-
|
|
133
|
+
concurrent: int | None = typer.Option(
|
|
134
|
+
None,
|
|
135
135
|
help="Maximum number of requests to execute at the same time.",
|
|
136
|
-
envvar="
|
|
136
|
+
envvar="INFRAHUB_MAX_CONCURRENT_EXECUTION",
|
|
137
137
|
),
|
|
138
|
-
timeout: int = typer.Option(60, help="Timeout in sec", envvar="
|
|
138
|
+
timeout: int = typer.Option(60, help="Timeout in sec", envvar="INFRAHUB_TIMEOUT"),
|
|
139
139
|
variables: list[str] | None = typer.Argument(
|
|
140
140
|
None, help="Variables to pass along with the query. Format key=value key=value."
|
|
141
141
|
),
|
infrahub_sdk/ctl/exporter.py
CHANGED
|
@@ -26,9 +26,9 @@ def dump(
|
|
|
26
26
|
concurrent: int = typer.Option(
|
|
27
27
|
4,
|
|
28
28
|
help="Maximum number of requests to execute at the same time.",
|
|
29
|
-
envvar="
|
|
29
|
+
envvar="INFRAHUB_MAX_CONCURRENT_EXECUTION",
|
|
30
30
|
),
|
|
31
|
-
timeout: int = typer.Option(60, help="Timeout in sec", envvar="
|
|
31
|
+
timeout: int = typer.Option(60, help="Timeout in sec", envvar="INFRAHUB_TIMEOUT"),
|
|
32
32
|
exclude: list[str] = typer.Option(
|
|
33
33
|
["CoreAccount"],
|
|
34
34
|
help="Prevent node kind(s) from being exported, CoreAccount is excluded by default",
|
infrahub_sdk/ctl/importer.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from asyncio import run as aiorun
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
|
|
@@ -24,12 +26,12 @@ def load(
|
|
|
24
26
|
quiet: bool = typer.Option(False, help="No console output"),
|
|
25
27
|
_: str = CONFIG_PARAM,
|
|
26
28
|
branch: str = typer.Option("main", help="Branch from which to export"),
|
|
27
|
-
concurrent: int = typer.Option(
|
|
28
|
-
|
|
29
|
+
concurrent: int | None = typer.Option(
|
|
30
|
+
None,
|
|
29
31
|
help="Maximum number of requests to execute at the same time.",
|
|
30
|
-
envvar="
|
|
32
|
+
envvar="INFRAHUB_MAX_CONCURRENT_EXECUTION",
|
|
31
33
|
),
|
|
32
|
-
timeout: int = typer.Option(60, help="Timeout in sec", envvar="
|
|
34
|
+
timeout: int = typer.Option(60, help="Timeout in sec", envvar="INFRAHUB_TIMEOUT"),
|
|
33
35
|
) -> None:
|
|
34
36
|
"""Import nodes and their relationships into the database."""
|
|
35
37
|
console = Console()
|
infrahub_sdk/ctl/repository.py
CHANGED
|
@@ -6,13 +6,14 @@ import typer
|
|
|
6
6
|
import yaml
|
|
7
7
|
from pydantic import ValidationError
|
|
8
8
|
from rich.console import Console
|
|
9
|
+
from rich.table import Table
|
|
9
10
|
|
|
10
11
|
from infrahub_sdk.ctl.client import initialize_client
|
|
11
12
|
|
|
12
13
|
from ..async_typer import AsyncTyper
|
|
13
14
|
from ..ctl.exceptions import FileNotValidError
|
|
14
15
|
from ..ctl.utils import init_logging
|
|
15
|
-
from ..graphql import Mutation
|
|
16
|
+
from ..graphql import Mutation, Query
|
|
16
17
|
from ..schema.repository import InfrahubRepositoryConfig
|
|
17
18
|
from ._file import read_file
|
|
18
19
|
from .parameters import CONFIG_PARAM
|
|
@@ -102,3 +103,57 @@ async def add(
|
|
|
102
103
|
)
|
|
103
104
|
|
|
104
105
|
await client.execute_graphql(query=query.render(), branch_name=branch, tracker="mutation-repository-create")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@app.command()
|
|
109
|
+
async def list(
|
|
110
|
+
branch: str | None = None,
|
|
111
|
+
debug: bool = False,
|
|
112
|
+
_: str = CONFIG_PARAM,
|
|
113
|
+
) -> None:
|
|
114
|
+
init_logging(debug=debug)
|
|
115
|
+
|
|
116
|
+
client = initialize_client(branch=branch)
|
|
117
|
+
|
|
118
|
+
repo_status_query = {
|
|
119
|
+
"CoreGenericRepository": {
|
|
120
|
+
"edges": {
|
|
121
|
+
"node": {
|
|
122
|
+
"__typename": None,
|
|
123
|
+
"name": {"value": None},
|
|
124
|
+
"operational_status": {"value": None},
|
|
125
|
+
"sync_status": {"value": None},
|
|
126
|
+
"internal_status": {"value": None},
|
|
127
|
+
"... on CoreReadOnlyRepository": {
|
|
128
|
+
"ref": {"value": None},
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
query = Query(name="GetRepositoryStatus", query=repo_status_query)
|
|
136
|
+
resp = await client.execute_graphql(query=query.render(), branch_name=branch, tracker="query-repository-list")
|
|
137
|
+
|
|
138
|
+
table = Table(title="List of all Repositories")
|
|
139
|
+
|
|
140
|
+
table.add_column("Name", justify="right", style="cyan", no_wrap=True)
|
|
141
|
+
table.add_column("Type")
|
|
142
|
+
table.add_column("Operational status")
|
|
143
|
+
table.add_column("Sync status")
|
|
144
|
+
table.add_column("Internal status")
|
|
145
|
+
table.add_column("Ref")
|
|
146
|
+
|
|
147
|
+
for repository_node in resp["CoreGenericRepository"]["edges"]:
|
|
148
|
+
repository = repository_node["node"]
|
|
149
|
+
|
|
150
|
+
table.add_row(
|
|
151
|
+
repository["name"]["value"],
|
|
152
|
+
repository["__typename"],
|
|
153
|
+
repository["operational_status"]["value"],
|
|
154
|
+
repository["sync_status"]["value"],
|
|
155
|
+
repository["internal_status"]["value"],
|
|
156
|
+
repository["ref"]["value"] if "ref" in repository else "",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
console.print(table)
|
infrahub_sdk/generator.py
CHANGED
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
from abc import abstractmethod
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from infrahub_sdk.repository import GitRepoManager
|
|
8
8
|
|
|
9
9
|
from .exceptions import UninitializedError
|
|
10
10
|
|
|
@@ -30,7 +30,7 @@ class InfrahubGenerator:
|
|
|
30
30
|
) -> None:
|
|
31
31
|
self.query = query
|
|
32
32
|
self.branch = branch
|
|
33
|
-
self.git:
|
|
33
|
+
self.git: GitRepoManager | None = None
|
|
34
34
|
self.params = params or {}
|
|
35
35
|
self.root_directory = root_directory or os.getcwd()
|
|
36
36
|
self.generator_instance = generator_instance
|
|
@@ -81,7 +81,7 @@ class InfrahubGenerator:
|
|
|
81
81
|
return self.branch
|
|
82
82
|
|
|
83
83
|
if not self.git:
|
|
84
|
-
self.git =
|
|
84
|
+
self.git = GitRepoManager(self.root_directory)
|
|
85
85
|
|
|
86
86
|
self.branch = str(self.git.active_branch)
|
|
87
87
|
|
infrahub_sdk/node.py
CHANGED
|
@@ -1074,7 +1074,7 @@ class InfrahubNode(InfrahubNodeBase):
|
|
|
1074
1074
|
timeout: int | None = None,
|
|
1075
1075
|
) -> Self:
|
|
1076
1076
|
if not schema:
|
|
1077
|
-
node_kind = data.get("__typename"
|
|
1077
|
+
node_kind = data.get("__typename") or data.get("node", {}).get("__typename", None)
|
|
1078
1078
|
if not node_kind:
|
|
1079
1079
|
raise ValueError("Unable to determine the type of the node, __typename not present in data")
|
|
1080
1080
|
schema = await client.schema.get(kind=node_kind, branch=branch, timeout=timeout)
|
|
@@ -1594,7 +1594,7 @@ class InfrahubNodeSync(InfrahubNodeBase):
|
|
|
1594
1594
|
timeout: int | None = None,
|
|
1595
1595
|
) -> Self:
|
|
1596
1596
|
if not schema:
|
|
1597
|
-
node_kind = data.get("__typename"
|
|
1597
|
+
node_kind = data.get("__typename") or data.get("node", {}).get("__typename", None)
|
|
1598
1598
|
if not node_kind:
|
|
1599
1599
|
raise ValueError("Unable to determine the type of the node, __typename not present in data")
|
|
1600
1600
|
schema = client.schema.get(kind=node_kind, branch=branch, timeout=timeout)
|
|
@@ -6,7 +6,6 @@ from typing import TYPE_CHECKING, Any
|
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
8
|
import ujson
|
|
9
|
-
from git.exc import InvalidGitRepositoryError
|
|
10
9
|
|
|
11
10
|
from ..exceptions import InvalidResourceConfigError
|
|
12
11
|
from ..models import InfrahubInputOutputTest
|
|
@@ -28,7 +27,6 @@ class InfrahubItem(pytest.Item):
|
|
|
28
27
|
**kwargs: dict[str, Any],
|
|
29
28
|
):
|
|
30
29
|
super().__init__(*args, **kwargs) # type: ignore[arg-type]
|
|
31
|
-
|
|
32
30
|
self.resource_name: str = resource_name
|
|
33
31
|
self.resource_config: InfrahubRepositoryConfigElement = resource_config
|
|
34
32
|
self.test: InfrahubTest = test
|
|
@@ -68,9 +66,6 @@ class InfrahubItem(pytest.Item):
|
|
|
68
66
|
"""Run the test logic."""
|
|
69
67
|
|
|
70
68
|
def repr_failure(self, excinfo: pytest.ExceptionInfo, style: str | None = None) -> str: # noqa: ARG002
|
|
71
|
-
if isinstance(excinfo.value, InvalidGitRepositoryError):
|
|
72
|
-
return f"Invalid Git repository at {excinfo.value}"
|
|
73
|
-
|
|
74
69
|
return str(excinfo.value)
|
|
75
70
|
|
|
76
71
|
def reportinfo(self) -> tuple[Path | str, int | None, str]:
|
|
@@ -40,7 +40,7 @@ class InfrahubGraphQLQueryItem(InfrahubItem):
|
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
if isinstance(excinfo.value, OutputMatchError):
|
|
43
|
-
return "
|
|
43
|
+
return f"{excinfo.value.message}\n{excinfo.value.differences}"
|
|
44
44
|
|
|
45
45
|
return super().repr_failure(excinfo, style=style)
|
|
46
46
|
|
|
@@ -79,7 +79,7 @@ class InfrahubJinja2Item(InfrahubItem):
|
|
|
79
79
|
return "\n".join(["Syntax error detected in the template", excinfo.value.message or ""])
|
|
80
80
|
|
|
81
81
|
if isinstance(excinfo.value, OutputMatchError):
|
|
82
|
-
return "
|
|
82
|
+
return f"{excinfo.value.message}\n{excinfo.value.differences}"
|
|
83
83
|
|
|
84
84
|
return super().repr_failure(excinfo, style=style)
|
|
85
85
|
|
|
@@ -62,7 +62,7 @@ class InfrahubPythonTransformItem(InfrahubItem):
|
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
if isinstance(excinfo.value, OutputMatchError):
|
|
65
|
-
return "
|
|
65
|
+
return f"{excinfo.value.message}\n{excinfo.value.differences}"
|
|
66
66
|
|
|
67
67
|
return super().repr_failure(excinfo, style=style)
|
|
68
68
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from dulwich import porcelain
|
|
6
|
+
from dulwich.repo import Repo
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GitRepoManager:
|
|
10
|
+
def __init__(self, root_directory: str, branch: str = "main"):
|
|
11
|
+
self.root_directory = root_directory
|
|
12
|
+
self.branch = branch
|
|
13
|
+
self.git: Repo = self.initialize_repo()
|
|
14
|
+
|
|
15
|
+
def initialize_repo(self) -> Repo:
|
|
16
|
+
# Check if the directory already has a repository
|
|
17
|
+
|
|
18
|
+
root_path = Path(self.root_directory)
|
|
19
|
+
|
|
20
|
+
if root_path.exists() and (root_path / ".git").is_dir():
|
|
21
|
+
repo = Repo(self.root_directory) # Open existing repo
|
|
22
|
+
else:
|
|
23
|
+
repo = Repo.init(self.root_directory, default_branch=self.branch.encode("utf-8"))
|
|
24
|
+
|
|
25
|
+
if not repo:
|
|
26
|
+
raise ValueError("Failed to initialize or open a repository.")
|
|
27
|
+
|
|
28
|
+
return repo
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def active_branch(self) -> str | None:
|
|
32
|
+
active_branch = porcelain.active_branch(self.root_directory).decode("utf-8")
|
|
33
|
+
return active_branch
|
|
@@ -7,10 +7,11 @@ from enum import Enum
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import TYPE_CHECKING
|
|
9
9
|
|
|
10
|
-
from
|
|
10
|
+
from dulwich import porcelain
|
|
11
11
|
|
|
12
12
|
from infrahub_sdk.graphql import Mutation
|
|
13
13
|
from infrahub_sdk.protocols import CoreGenericRepository
|
|
14
|
+
from infrahub_sdk.repository import GitRepoManager
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from infrahub_sdk import InfrahubClient
|
|
@@ -37,14 +38,14 @@ class GitRepo:
|
|
|
37
38
|
|
|
38
39
|
type: GitRepoType = GitRepoType.INTEGRATED
|
|
39
40
|
|
|
40
|
-
_repo:
|
|
41
|
+
_repo: GitRepoManager | None = None
|
|
41
42
|
initial_branch: str = "main"
|
|
42
43
|
directories_to_ignore: list[str] = field(default_factory=list)
|
|
43
44
|
remote_directory_name: str = "/remote"
|
|
44
45
|
_branches: list[str] = field(default_factory=list)
|
|
45
46
|
|
|
46
47
|
@property
|
|
47
|
-
def repo(self) ->
|
|
48
|
+
def repo(self) -> GitRepoManager:
|
|
48
49
|
if self._repo:
|
|
49
50
|
return self._repo
|
|
50
51
|
raise ValueError("Repo hasn't been initialized yet")
|
|
@@ -62,12 +63,17 @@ class GitRepo:
|
|
|
62
63
|
dst=self.dst_directory / self.name,
|
|
63
64
|
ignore=shutil.ignore_patterns(".git"),
|
|
64
65
|
)
|
|
65
|
-
self._repo = Repo.init(self.dst_directory / self.name, initial_branch=self.initial_branch)
|
|
66
|
-
for untracked in self.repo.untracked_files:
|
|
67
|
-
self.repo.index.add(untracked)
|
|
68
|
-
self.repo.index.commit("First commit")
|
|
69
66
|
|
|
70
|
-
self.
|
|
67
|
+
self._repo = GitRepoManager(str(Path(self.dst_directory / self.name)), branch=self.initial_branch)
|
|
68
|
+
|
|
69
|
+
files = list(
|
|
70
|
+
porcelain.get_untracked_paths(self._repo.git.path, self._repo.git.path, self._repo.git.open_index())
|
|
71
|
+
)
|
|
72
|
+
files_to_add = [str(Path(self._repo.git.path) / t) for t in files]
|
|
73
|
+
if files_to_add:
|
|
74
|
+
porcelain.add(repo=self._repo.git.path, paths=files_to_add)
|
|
75
|
+
porcelain.commit(repo=self._repo.git.path, message="First commit")
|
|
76
|
+
porcelain.checkout_branch(self._repo.git, self.initial_branch.encode("utf-8"))
|
|
71
77
|
|
|
72
78
|
async def add_to_infrahub(self, client: InfrahubClient, branch: str | None = None) -> dict:
|
|
73
79
|
input_data = {
|
infrahub_sdk/transforms.py
CHANGED
|
@@ -5,7 +5,7 @@ import os
|
|
|
5
5
|
from abc import abstractmethod
|
|
6
6
|
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from infrahub_sdk.repository import GitRepoManager
|
|
9
9
|
|
|
10
10
|
from .exceptions import UninitializedError
|
|
11
11
|
|
|
@@ -27,7 +27,7 @@ class InfrahubTransform:
|
|
|
27
27
|
server_url: str = "",
|
|
28
28
|
client: InfrahubClient | None = None,
|
|
29
29
|
):
|
|
30
|
-
self.git:
|
|
30
|
+
self.git: GitRepoManager
|
|
31
31
|
|
|
32
32
|
self.branch = branch
|
|
33
33
|
self.server_url = server_url or os.environ.get("INFRAHUB_URL", "http://127.0.0.1:8000")
|
|
@@ -56,7 +56,7 @@ class InfrahubTransform:
|
|
|
56
56
|
return self.branch
|
|
57
57
|
|
|
58
58
|
if not hasattr(self, "git") or not self.git:
|
|
59
|
-
self.git =
|
|
59
|
+
self.git = GitRepoManager(self.root_directory)
|
|
60
60
|
|
|
61
61
|
self.branch = str(self.git.active_branch)
|
|
62
62
|
|