infrahub-server 1.1.7__py3-none-any.whl → 1.1.8__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/diff/enricher/cardinality_one.py +5 -0
- infrahub/core/diff/enricher/hierarchy.py +17 -4
- infrahub/core/diff/enricher/labels.py +5 -0
- infrahub/core/diff/enricher/path_identifier.py +5 -0
- infrahub/core/diff/model/path.py +24 -1
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/save.py +188 -182
- infrahub/core/diff/query/summary_counts_enricher.py +51 -4
- infrahub/core/diff/repository/deserializer.py +8 -3
- infrahub/core/diff/repository/repository.py +156 -38
- infrahub/core/diff/tasks.py +4 -4
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +3 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
- infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
- infrahub/core/migrations/query/node_duplicate.py +38 -18
- infrahub/core/migrations/schema/node_remove.py +26 -12
- infrahub/core/migrations/shared.py +10 -8
- infrahub/core/node/__init__.py +13 -8
- infrahub/core/node/constraints/grouped_uniqueness.py +16 -3
- infrahub/core/query/attribute.py +2 -0
- infrahub/core/query/node.py +66 -19
- infrahub/core/query/relationship.py +105 -16
- infrahub/core/query/resource_manager.py +2 -0
- infrahub/core/relationship/model.py +8 -12
- infrahub/core/schema/definitions/core.py +1 -0
- infrahub/database/__init__.py +1 -0
- infrahub/dependencies/builder/diff/deserializer.py +3 -1
- infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
- infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
- infrahub/graphql/mutations/diff.py +17 -10
- infrahub/graphql/mutations/resource_manager.py +3 -3
- infrahub_sdk/batch.py +2 -2
- infrahub_sdk/client.py +10 -2
- infrahub_sdk/config.py +4 -1
- infrahub_sdk/ctl/check.py +4 -4
- infrahub_sdk/ctl/cli_commands.py +16 -11
- infrahub_sdk/ctl/exceptions.py +0 -6
- infrahub_sdk/ctl/exporter.py +1 -1
- infrahub_sdk/ctl/generator.py +5 -5
- infrahub_sdk/ctl/importer.py +3 -2
- infrahub_sdk/ctl/menu.py +1 -1
- infrahub_sdk/ctl/object.py +1 -1
- infrahub_sdk/ctl/repository.py +23 -15
- infrahub_sdk/ctl/schema.py +2 -2
- infrahub_sdk/ctl/utils.py +6 -5
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/data.py +1 -1
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +8 -8
- infrahub_sdk/protocols.py +0 -1
- infrahub_sdk/schema/__init__.py +0 -3
- infrahub_sdk/testing/docker.py +30 -0
- infrahub_sdk/testing/schemas/animal.py +9 -0
- infrahub_sdk/transfer/exporter/json.py +1 -1
- infrahub_sdk/utils.py +11 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.8.dist-info}/METADATA +1 -1
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.8.dist-info}/RECORD +65 -62
- infrahub_sdk/ctl/_file.py +0 -13
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.8.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.8.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.8.dist-info}/entry_points.txt +0 -0
infrahub_sdk/ctl/generator.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
7
|
from rich.console import Console
|
|
@@ -9,7 +9,7 @@ from rich.console import Console
|
|
|
9
9
|
from ..ctl import config
|
|
10
10
|
from ..ctl.client import initialize_client
|
|
11
11
|
from ..ctl.repository import get_repository_config
|
|
12
|
-
from ..ctl.utils import execute_graphql_query, parse_cli_vars
|
|
12
|
+
from ..ctl.utils import execute_graphql_query, init_logging, parse_cli_vars
|
|
13
13
|
from ..exceptions import ModuleImportError
|
|
14
14
|
from ..node import InfrahubNode
|
|
15
15
|
|
|
@@ -20,11 +20,12 @@ if TYPE_CHECKING:
|
|
|
20
20
|
async def run(
|
|
21
21
|
generator_name: str,
|
|
22
22
|
path: str, # noqa: ARG001
|
|
23
|
-
debug: bool,
|
|
23
|
+
debug: bool,
|
|
24
24
|
list_available: bool,
|
|
25
25
|
branch: str | None = None,
|
|
26
|
-
variables: list[str]
|
|
26
|
+
variables: Optional[list[str]] = None,
|
|
27
27
|
) -> None:
|
|
28
|
+
init_logging(debug=debug)
|
|
28
29
|
repository_config = get_repository_config(Path(config.INFRAHUB_REPO_CONFIG_FILE))
|
|
29
30
|
|
|
30
31
|
if list_available or not generator_name:
|
|
@@ -34,7 +35,6 @@ async def run(
|
|
|
34
35
|
generator_config = repository_config.get_generator_definition(name=generator_name)
|
|
35
36
|
|
|
36
37
|
console = Console()
|
|
37
|
-
|
|
38
38
|
relative_path = str(generator_config.file_path.parent) if generator_config.file_path.parent != Path() else None
|
|
39
39
|
|
|
40
40
|
try:
|
infrahub_sdk/ctl/importer.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from asyncio import run as aiorun
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
7
|
import typer
|
|
7
8
|
from rich.console import Console
|
|
@@ -25,8 +26,8 @@ def load(
|
|
|
25
26
|
),
|
|
26
27
|
quiet: bool = typer.Option(False, help="No console output"),
|
|
27
28
|
_: str = CONFIG_PARAM,
|
|
28
|
-
branch: str = typer.Option(
|
|
29
|
-
concurrent: int
|
|
29
|
+
branch: str = typer.Option(None, help="Branch from which to export"),
|
|
30
|
+
concurrent: Optional[int] = typer.Option(
|
|
30
31
|
None,
|
|
31
32
|
help="Maximum number of requests to execute at the same time.",
|
|
32
33
|
envvar="INFRAHUB_MAX_CONCURRENT_EXECUTION",
|
infrahub_sdk/ctl/menu.py
CHANGED
|
@@ -27,7 +27,7 @@ def callback() -> None:
|
|
|
27
27
|
async def load(
|
|
28
28
|
menus: list[Path],
|
|
29
29
|
debug: bool = False,
|
|
30
|
-
branch: str = typer.Option(
|
|
30
|
+
branch: str = typer.Option(None, help="Branch on which to load the menu."),
|
|
31
31
|
_: str = CONFIG_PARAM,
|
|
32
32
|
) -> None:
|
|
33
33
|
"""Load one or multiple menu files into Infrahub."""
|
infrahub_sdk/ctl/object.py
CHANGED
|
@@ -27,7 +27,7 @@ def callback() -> None:
|
|
|
27
27
|
async def load(
|
|
28
28
|
paths: list[Path],
|
|
29
29
|
debug: bool = False,
|
|
30
|
-
branch: str = typer.Option(
|
|
30
|
+
branch: str = typer.Option(None, help="Branch on which to load the objects."),
|
|
31
31
|
_: str = CONFIG_PARAM,
|
|
32
32
|
) -> None:
|
|
33
33
|
"""Load one or multiple objects files into Infrahub."""
|
infrahub_sdk/ctl/repository.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Optional
|
|
4
5
|
|
|
5
6
|
import typer
|
|
6
7
|
import yaml
|
|
@@ -8,15 +9,14 @@ from pydantic import ValidationError
|
|
|
8
9
|
from rich.console import Console
|
|
9
10
|
from rich.table import Table
|
|
10
11
|
|
|
11
|
-
from infrahub_sdk.ctl.client import initialize_client
|
|
12
|
-
|
|
13
12
|
from ..async_typer import AsyncTyper
|
|
14
|
-
from ..
|
|
15
|
-
from ..ctl.utils import init_logging
|
|
13
|
+
from ..exceptions import FileNotValidError
|
|
16
14
|
from ..graphql import Mutation, Query
|
|
17
15
|
from ..schema.repository import InfrahubRepositoryConfig
|
|
18
|
-
from
|
|
16
|
+
from ..utils import read_file
|
|
17
|
+
from .client import initialize_client
|
|
19
18
|
from .parameters import CONFIG_PARAM
|
|
19
|
+
from .utils import init_logging
|
|
20
20
|
|
|
21
21
|
app = AsyncTyper()
|
|
22
22
|
console = Console()
|
|
@@ -69,12 +69,11 @@ async def add(
|
|
|
69
69
|
name: str,
|
|
70
70
|
location: str,
|
|
71
71
|
description: str = "",
|
|
72
|
-
username: str
|
|
72
|
+
username: Optional[str] = None,
|
|
73
73
|
password: str = "",
|
|
74
|
-
|
|
74
|
+
ref: str = "",
|
|
75
75
|
read_only: bool = False,
|
|
76
76
|
debug: bool = False,
|
|
77
|
-
branch: str = typer.Option("main", help="Branch on which to add the repository."),
|
|
78
77
|
_: str = CONFIG_PARAM,
|
|
79
78
|
) -> None:
|
|
80
79
|
"""Add a new repository."""
|
|
@@ -86,15 +85,24 @@ async def add(
|
|
|
86
85
|
"name": {"value": name},
|
|
87
86
|
"location": {"value": location},
|
|
88
87
|
"description": {"value": description},
|
|
89
|
-
"commit": {"value": commit},
|
|
90
88
|
},
|
|
91
89
|
}
|
|
90
|
+
if read_only:
|
|
91
|
+
input_data["data"]["ref"] = {"value": ref}
|
|
92
|
+
else:
|
|
93
|
+
input_data["data"]["default_branch"] = {"value": ref}
|
|
92
94
|
|
|
93
95
|
client = initialize_client()
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
if username or password:
|
|
98
|
+
credential = await client.create(
|
|
99
|
+
kind="CorePasswordCredential",
|
|
100
|
+
name=name,
|
|
101
|
+
username=username,
|
|
102
|
+
password=password,
|
|
103
|
+
)
|
|
104
|
+
await credential.save(allow_upsert=True)
|
|
105
|
+
input_data["data"]["credential"] = {"id": credential.id}
|
|
98
106
|
|
|
99
107
|
query = Mutation(
|
|
100
108
|
mutation="CoreReadOnlyRepositoryCreate" if read_only else "CoreRepositoryCreate",
|
|
@@ -102,18 +110,18 @@ async def add(
|
|
|
102
110
|
query={"ok": None},
|
|
103
111
|
)
|
|
104
112
|
|
|
105
|
-
await client.execute_graphql(query=query.render(),
|
|
113
|
+
await client.execute_graphql(query=query.render(), tracker="mutation-repository-create")
|
|
106
114
|
|
|
107
115
|
|
|
108
116
|
@app.command()
|
|
109
117
|
async def list(
|
|
110
|
-
branch: str
|
|
118
|
+
branch: Optional[str] = typer.Option(None, help="Branch on which to list repositories."),
|
|
111
119
|
debug: bool = False,
|
|
112
120
|
_: str = CONFIG_PARAM,
|
|
113
121
|
) -> None:
|
|
114
122
|
init_logging(debug=debug)
|
|
115
123
|
|
|
116
|
-
client = initialize_client(
|
|
124
|
+
client = initialize_client()
|
|
117
125
|
|
|
118
126
|
repo_status_query = {
|
|
119
127
|
"CoreGenericRepository": {
|
infrahub_sdk/ctl/schema.py
CHANGED
|
@@ -108,7 +108,7 @@ def get_node(schemas_data: list[dict], schema_index: int, node_index: int) -> di
|
|
|
108
108
|
async def load(
|
|
109
109
|
schemas: list[Path],
|
|
110
110
|
debug: bool = False,
|
|
111
|
-
branch: str = typer.Option(
|
|
111
|
+
branch: str = typer.Option(None, help="Branch on which to load the schema."),
|
|
112
112
|
wait: int = typer.Option(0, help="Time in seconds to wait until the schema has converged across all workers"),
|
|
113
113
|
_: str = CONFIG_PARAM,
|
|
114
114
|
) -> None:
|
|
@@ -159,7 +159,7 @@ async def load(
|
|
|
159
159
|
async def check(
|
|
160
160
|
schemas: list[Path],
|
|
161
161
|
debug: bool = False,
|
|
162
|
-
branch: str = typer.Option(
|
|
162
|
+
branch: str = typer.Option(None, help="Branch on which to check the schema."),
|
|
163
163
|
_: str = CONFIG_PARAM,
|
|
164
164
|
) -> None:
|
|
165
165
|
"""Check if schema files are valid and what would be the impact of loading them with Infrahub."""
|
infrahub_sdk/ctl/utils.py
CHANGED
|
@@ -6,7 +6,7 @@ import traceback
|
|
|
6
6
|
from collections.abc import Coroutine
|
|
7
7
|
from functools import wraps
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import TYPE_CHECKING, Any, Callable, NoReturn, TypeVar
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, NoReturn, Optional, TypeVar
|
|
10
10
|
|
|
11
11
|
import pendulum
|
|
12
12
|
import typer
|
|
@@ -17,10 +17,10 @@ from rich.console import Console
|
|
|
17
17
|
from rich.logging import RichHandler
|
|
18
18
|
from rich.markup import escape
|
|
19
19
|
|
|
20
|
-
from ..ctl.exceptions import FileNotValidError, QueryNotFoundError
|
|
21
20
|
from ..exceptions import (
|
|
22
21
|
AuthenticationError,
|
|
23
22
|
Error,
|
|
23
|
+
FileNotValidError,
|
|
24
24
|
GraphQLError,
|
|
25
25
|
NodeNotFoundError,
|
|
26
26
|
ResourceNotDefinedError,
|
|
@@ -30,6 +30,7 @@ from ..exceptions import (
|
|
|
30
30
|
)
|
|
31
31
|
from ..yaml import YamlFile
|
|
32
32
|
from .client import initialize_client_sync
|
|
33
|
+
from .exceptions import QueryNotFoundError
|
|
33
34
|
|
|
34
35
|
if TYPE_CHECKING:
|
|
35
36
|
from ..schema.repository import InfrahubRepositoryConfig
|
|
@@ -88,7 +89,7 @@ def catch_exception(
|
|
|
88
89
|
async def async_wrapper(*args: Any, **kwargs: Any) -> T:
|
|
89
90
|
try:
|
|
90
91
|
return await func(*args, **kwargs)
|
|
91
|
-
except (Error, Exception) as exc:
|
|
92
|
+
except (Error, Exception) as exc:
|
|
92
93
|
return handle_exception(exc=exc, console=console, exit_code=exit_code)
|
|
93
94
|
|
|
94
95
|
return async_wrapper
|
|
@@ -97,7 +98,7 @@ def catch_exception(
|
|
|
97
98
|
def wrapper(*args: Any, **kwargs: Any) -> T:
|
|
98
99
|
try:
|
|
99
100
|
return func(*args, **kwargs)
|
|
100
|
-
except (Error, Exception) as exc:
|
|
101
|
+
except (Error, Exception) as exc:
|
|
101
102
|
return handle_exception(exc=exc, console=console, exit_code=exit_code)
|
|
102
103
|
|
|
103
104
|
return wrapper
|
|
@@ -144,7 +145,7 @@ def print_graphql_errors(console: Console, errors: list) -> None:
|
|
|
144
145
|
console.print(f"[red]{escape(str(error))}")
|
|
145
146
|
|
|
146
147
|
|
|
147
|
-
def parse_cli_vars(variables: list[str]
|
|
148
|
+
def parse_cli_vars(variables: Optional[list[str]]) -> dict[str, str]:
|
|
148
149
|
if not variables:
|
|
149
150
|
return {}
|
|
150
151
|
|
infrahub_sdk/ctl/validate.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Optional
|
|
5
6
|
|
|
6
7
|
import typer
|
|
7
8
|
import ujson
|
|
@@ -57,7 +58,7 @@ async def validate_schema(schema: Path, _: str = CONFIG_PARAM) -> None:
|
|
|
57
58
|
@catch_exception(console=console)
|
|
58
59
|
def validate_graphql(
|
|
59
60
|
query: str,
|
|
60
|
-
variables: list[str]
|
|
61
|
+
variables: Optional[list[str]] = typer.Argument(
|
|
61
62
|
None, help="Variables to pass along with the query. Format key=value key=value."
|
|
62
63
|
),
|
|
63
64
|
debug: bool = typer.Option(False, help="Display more troubleshooting information."),
|
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():
|
|
24
24
|
if info.internal_status == "staging":
|
|
25
25
|
return branch
|
|
26
26
|
return None
|
infrahub_sdk/exceptions.py
CHANGED
|
@@ -121,6 +121,12 @@ class AuthenticationError(Error):
|
|
|
121
121
|
super().__init__(self.message)
|
|
122
122
|
|
|
123
123
|
|
|
124
|
+
class URLNotFoundError(Error):
|
|
125
|
+
def __init__(self, url: str):
|
|
126
|
+
self.message = f"`{url}` not found."
|
|
127
|
+
super().__init__(self.message)
|
|
128
|
+
|
|
129
|
+
|
|
124
130
|
class FeatureNotSupportedError(Error):
|
|
125
131
|
"""Raised when trying to use a method on a node that doesn't support it."""
|
|
126
132
|
|
|
@@ -131,3 +137,9 @@ class UninitializedError(Error):
|
|
|
131
137
|
|
|
132
138
|
class InvalidResponseError(Error):
|
|
133
139
|
"""Raised when an object requires an initialization step before use"""
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class FileNotValidError(Error):
|
|
143
|
+
def __init__(self, name: str, message: str = ""):
|
|
144
|
+
self.message = message or f"Cannot parse '{name}' content."
|
|
145
|
+
super().__init__(self.message)
|
infrahub_sdk/generator.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
from abc import abstractmethod
|
|
5
6
|
from typing import TYPE_CHECKING
|
|
@@ -27,6 +28,7 @@ class InfrahubGenerator:
|
|
|
27
28
|
generator_instance: str = "",
|
|
28
29
|
params: dict | None = None,
|
|
29
30
|
convert_query_response: bool = False,
|
|
31
|
+
logger: logging.Logger | None = None,
|
|
30
32
|
) -> None:
|
|
31
33
|
self.query = query
|
|
32
34
|
self.branch = branch
|
|
@@ -41,6 +43,7 @@ class InfrahubGenerator:
|
|
|
41
43
|
self._related_nodes: list[InfrahubNode] = []
|
|
42
44
|
self.infrahub_node = infrahub_node
|
|
43
45
|
self.convert_query_response = convert_query_response
|
|
46
|
+
self.logger = logger if logger else logging.getLogger("infrahub.tasks")
|
|
44
47
|
|
|
45
48
|
@property
|
|
46
49
|
def store(self) -> NodeStore:
|
infrahub_sdk/node.py
CHANGED
|
@@ -25,7 +25,6 @@ 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
|
|
29
28
|
|
|
30
29
|
PROPERTIES_FLAG = ["is_visible", "is_protected"]
|
|
31
30
|
PROPERTIES_OBJECT = ["source", "owner"]
|
|
@@ -188,6 +187,7 @@ class RelatedNodeBase:
|
|
|
188
187
|
if node_data:
|
|
189
188
|
self._id = node_data.get("id", None)
|
|
190
189
|
self._hfid = node_data.get("hfid", None)
|
|
190
|
+
self._kind = node_data.get("kind", None)
|
|
191
191
|
self._display_label = node_data.get("display_label", None)
|
|
192
192
|
self._typename = node_data.get("__typename", None)
|
|
193
193
|
|
|
@@ -256,6 +256,8 @@ class RelatedNodeBase:
|
|
|
256
256
|
data["id"] = self.id
|
|
257
257
|
elif self.hfid is not None:
|
|
258
258
|
data["hfid"] = self.hfid
|
|
259
|
+
if self._kind is not None:
|
|
260
|
+
data["kind"] = self._kind
|
|
259
261
|
|
|
260
262
|
for prop_name in self._properties:
|
|
261
263
|
if getattr(self, prop_name) is not None:
|
|
@@ -801,7 +803,7 @@ class InfrahubNodeBase:
|
|
|
801
803
|
Returns:
|
|
802
804
|
dict[str, Dict]: Representation of an input data in dict format
|
|
803
805
|
"""
|
|
804
|
-
|
|
806
|
+
|
|
805
807
|
data = {}
|
|
806
808
|
variables = {}
|
|
807
809
|
|
|
@@ -1119,14 +1121,14 @@ class InfrahubNode(InfrahubNodeBase):
|
|
|
1119
1121
|
async def artifact_generate(self, name: str) -> None:
|
|
1120
1122
|
self._validate_artifact_support(ARTIFACT_GENERATE_FEATURE_NOT_SUPPORTED_MESSAGE)
|
|
1121
1123
|
|
|
1122
|
-
artifact = await self._client.get(kind="CoreArtifact",
|
|
1124
|
+
artifact = await self._client.get(kind="CoreArtifact", name__value=name, object__ids=[self.id])
|
|
1123
1125
|
await artifact.definition.fetch() # type: ignore[attr-defined]
|
|
1124
1126
|
await artifact.definition.peer.generate([artifact.id]) # type: ignore[attr-defined]
|
|
1125
1127
|
|
|
1126
1128
|
async def artifact_fetch(self, name: str) -> str | dict[str, Any]:
|
|
1127
1129
|
self._validate_artifact_support(ARTIFACT_GENERATE_FEATURE_NOT_SUPPORTED_MESSAGE)
|
|
1128
1130
|
|
|
1129
|
-
artifact = await self._client.get(kind="CoreArtifact",
|
|
1131
|
+
artifact = await self._client.get(kind="CoreArtifact", name__value=name, object__ids=[self.id])
|
|
1130
1132
|
content = await self._client.object_store.get(identifier=artifact.storage_id.value) # type: ignore[attr-defined]
|
|
1131
1133
|
return content
|
|
1132
1134
|
|
|
@@ -1251,7 +1253,6 @@ class InfrahubNode(InfrahubNodeBase):
|
|
|
1251
1253
|
Returns:
|
|
1252
1254
|
dict[str, Union[Any, Dict]]: GraphQL query in dictionary format
|
|
1253
1255
|
"""
|
|
1254
|
-
# pylint: disable=too-many-branches
|
|
1255
1256
|
|
|
1256
1257
|
data: dict[str, Any] = {}
|
|
1257
1258
|
|
|
@@ -1637,13 +1638,13 @@ class InfrahubNodeSync(InfrahubNodeBase):
|
|
|
1637
1638
|
|
|
1638
1639
|
def artifact_generate(self, name: str) -> None:
|
|
1639
1640
|
self._validate_artifact_support(ARTIFACT_GENERATE_FEATURE_NOT_SUPPORTED_MESSAGE)
|
|
1640
|
-
artifact = self._client.get(kind="CoreArtifact",
|
|
1641
|
+
artifact = self._client.get(kind="CoreArtifact", name__value=name, object__ids=[self.id])
|
|
1641
1642
|
artifact.definition.fetch() # type: ignore[attr-defined]
|
|
1642
1643
|
artifact.definition.peer.generate([artifact.id]) # type: ignore[attr-defined]
|
|
1643
1644
|
|
|
1644
1645
|
def artifact_fetch(self, name: str) -> str | dict[str, Any]:
|
|
1645
1646
|
self._validate_artifact_support(ARTIFACT_FETCH_FEATURE_NOT_SUPPORTED_MESSAGE)
|
|
1646
|
-
artifact = self._client.get(kind="CoreArtifact",
|
|
1647
|
+
artifact = self._client.get(kind="CoreArtifact", name__value=name, object__ids=[self.id])
|
|
1647
1648
|
content = self._client.object_store.get(identifier=artifact.storage_id.value) # type: ignore[attr-defined]
|
|
1648
1649
|
return content
|
|
1649
1650
|
|
|
@@ -1763,7 +1764,6 @@ class InfrahubNodeSync(InfrahubNodeBase):
|
|
|
1763
1764
|
Returns:
|
|
1764
1765
|
dict[str, Union[Any, Dict]]: GraphQL query in dictionary format
|
|
1765
1766
|
"""
|
|
1766
|
-
# pylint: disable=too-many-branches
|
|
1767
1767
|
|
|
1768
1768
|
data: dict[str, Any] = {}
|
|
1769
1769
|
|
infrahub_sdk/protocols.py
CHANGED
infrahub_sdk/schema/__init__.py
CHANGED
infrahub_sdk/testing/docker.py
CHANGED
|
@@ -1,10 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
1
5
|
import pytest
|
|
2
6
|
from infrahub_testcontainers.helpers import TestInfrahubDocker
|
|
7
|
+
from packaging.version import InvalidVersion, Version
|
|
3
8
|
|
|
4
9
|
from .. import Config, InfrahubClient, InfrahubClientSync
|
|
5
10
|
|
|
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
|
+
|
|
6
32
|
|
|
7
33
|
class TestInfrahubDockerClient(TestInfrahubDocker):
|
|
34
|
+
@pytest.fixture(scope="class")
|
|
35
|
+
def infrahub_version(self) -> str:
|
|
36
|
+
return INFRAHUB_VERSION
|
|
37
|
+
|
|
8
38
|
@pytest.fixture(scope="class")
|
|
9
39
|
def client(self, infrahub_port: int) -> InfrahubClient:
|
|
10
40
|
return InfrahubClient(
|
|
@@ -80,6 +80,7 @@ class SchemaAnimal:
|
|
|
80
80
|
namespace=NAMESPACE,
|
|
81
81
|
include_in_menu=True,
|
|
82
82
|
inherit_from=[TESTING_ANIMAL],
|
|
83
|
+
human_friendly_id=["owner__name__value", "name__value", "color__value"],
|
|
83
84
|
display_labels=["name__value", "breed__value", "color__value"],
|
|
84
85
|
order_by=["name__value"],
|
|
85
86
|
attributes=[
|
|
@@ -108,6 +109,14 @@ class SchemaAnimal:
|
|
|
108
109
|
identifier="person__animal",
|
|
109
110
|
cardinality="many",
|
|
110
111
|
direction=RelationshipDirection.INBOUND,
|
|
112
|
+
max_count=10,
|
|
113
|
+
),
|
|
114
|
+
Rel(
|
|
115
|
+
name="favorite_animal",
|
|
116
|
+
peer=TESTING_ANIMAL,
|
|
117
|
+
identifier="favorite_animal",
|
|
118
|
+
cardinality="one",
|
|
119
|
+
direction=RelationshipDirection.INBOUND,
|
|
111
120
|
),
|
|
112
121
|
Rel(
|
|
113
122
|
name="best_friends",
|
|
@@ -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(
|
|
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)
|
infrahub_sdk/utils.py
CHANGED
|
@@ -17,7 +17,7 @@ from graphql import (
|
|
|
17
17
|
|
|
18
18
|
from infrahub_sdk.repository import GitRepoManager
|
|
19
19
|
|
|
20
|
-
from .exceptions import JsonDecodeError
|
|
20
|
+
from .exceptions import FileNotValidError, JsonDecodeError
|
|
21
21
|
|
|
22
22
|
if TYPE_CHECKING:
|
|
23
23
|
from graphql import GraphQLResolveInfo
|
|
@@ -342,6 +342,16 @@ def write_to_file(path: Path, value: Any) -> bool:
|
|
|
342
342
|
return written is not None
|
|
343
343
|
|
|
344
344
|
|
|
345
|
+
def read_file(file_name: Path) -> str:
|
|
346
|
+
if not file_name.is_file():
|
|
347
|
+
raise FileNotValidError(name=str(file_name), message=f"{file_name} is not a valid file")
|
|
348
|
+
try:
|
|
349
|
+
with Path.open(file_name, encoding="utf-8") as fobj:
|
|
350
|
+
return fobj.read()
|
|
351
|
+
except UnicodeDecodeError as exc:
|
|
352
|
+
raise FileNotValidError(name=str(file_name), message=f"Unable to read {file_name} with utf-8 encoding") from exc
|
|
353
|
+
|
|
354
|
+
|
|
345
355
|
def get_user_permissions(data: list[dict]) -> dict:
|
|
346
356
|
groups = {}
|
|
347
357
|
for group in data:
|
infrahub_sdk/yaml.py
CHANGED
|
@@ -8,9 +8,8 @@ import yaml
|
|
|
8
8
|
from pydantic import BaseModel, Field
|
|
9
9
|
from typing_extensions import Self
|
|
10
10
|
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
13
|
-
from .utils import find_files
|
|
11
|
+
from .exceptions import FileNotValidError
|
|
12
|
+
from .utils import find_files, read_file
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class InfrahubFileApiVersion(str, Enum):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: infrahub-server
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.8
|
|
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
|