diff --git a/.github/file-filters.yml b/.github/file-filters.yml index 2b72ac7d..9efe506e 100644 --- a/.github/file-filters.yml +++ b/.github/file-filters.yml @@ -3,6 +3,9 @@ ci_config: &ci_config - ".github/workflows/ci.yml" - ".github/file-filters.yml" +coverage_config: &coverage_config + - "codecov.yml" + github_workflows: &github_workflows - ".github/workflows/*.yml" @@ -20,6 +23,8 @@ doc_files: &doc_files python_all: &python_all - "**/*.py" - *poetry_files + - *ci_config + - *coverage_config yaml_all: &yaml_all - "**/*.{yml,yaml}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ed1dc30..989c6e4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,7 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v4" - name: "Setup environment" - run: "pip install ruff==0.5.0" + run: "pip install ruff==0.7.1" - name: "Linting: ruff check" run: "ruff check ." - name: "Linting: ruff format" @@ -142,7 +142,7 @@ jobs: run: | pipx install poetry poetry config virtualenvs.prefer-active-python true - pip install invoke toml + pip install invoke toml codecov - name: "Install Package" run: "poetry install --all-extras" - name: "Mypy Tests" @@ -150,4 +150,23 @@ jobs: # - name: "Pylint Tests" # run: "poetry run pylint infrahub_sdk/" - name: "Unit Tests" - run: "poetry run pytest tests/unit/" + run: "poetry run pytest --cov infrahub_sdk tests/unit/" + - name: "Upload coverage to Codecov" + run: | + codecov --flags python-${{ matrix.python-version }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + # The pytest-cov plugin doesn't quite work with content that is + # auto-imported by our own infrahub pytest plugin, this workaround + # reports the missing lines + - name: "Report coverage for pytest-plugin" + if: matrix.python-version == '3.12' + run: | + source $(poetry env info --path)/bin/activate + coverage run --source=infrahub_sdk -m pytest tests/unit/pytest_plugin + coverage report -m + coverage xml + codecov --flags python-filler-${{ matrix.python-version }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.yamllint.yml b/.yamllint.yml index eb4e3fee..ab834544 100644 --- a/.yamllint.yml +++ b/.yamllint.yml @@ -4,6 +4,7 @@ extends: default ignore: | /.venv /examples + tests/unit/sdk/test_data/schema_encoding_error.yml rules: new-lines: disable diff --git a/changelog/+8dff6891.removed.md b/changelog/+8dff6891.removed.md new file mode 100644 index 00000000..a34332fb --- /dev/null +++ b/changelog/+8dff6891.removed.md @@ -0,0 +1 @@ +Breaking change: Removed all exports from infrahub_sdk/__init__.py except InfrahubClient, InfrahubClientSync and Config. If you previously imported other classes such as InfrahubNode from the root level these need to change to instead be an absolute path. diff --git a/changelog/+connection-timeout.fixed.md b/changelog/+connection-timeout.fixed.md new file mode 100644 index 00000000..a3a47ea4 --- /dev/null +++ b/changelog/+connection-timeout.fixed.md @@ -0,0 +1 @@ +Changed the default connection timeout in the SDK to 60s. diff --git a/changelog/+infrahubctl-menu.added.md b/changelog/+infrahubctl-menu.added.md new file mode 100644 index 00000000..6de99321 --- /dev/null +++ b/changelog/+infrahubctl-menu.added.md @@ -0,0 +1 @@ +Added `infrahubctl menu` command to load menu definitions into Infrahub diff --git a/changelog/+urlencode-url-parameters.fixed.md b/changelog/+urlencode-url-parameters.fixed.md new file mode 100644 index 00000000..47c99f7d --- /dev/null +++ b/changelog/+urlencode-url-parameters.fixed.md @@ -0,0 +1 @@ +Fixes an issue where InfrahubClient was not properly URL encoding URL parameters. diff --git a/changelog/102.fixed.md b/changelog/102.fixed.md new file mode 100644 index 00000000..bc4325fd --- /dev/null +++ b/changelog/102.fixed.md @@ -0,0 +1 @@ +CTL: Return friendly error on encoding violations when reading files. diff --git a/changelog/25.added.md b/changelog/25.added.md new file mode 100644 index 00000000..5ea6dad6 --- /dev/null +++ b/changelog/25.added.md @@ -0,0 +1 @@ +Add support for specific timeout per request on InfrahubClient and InfrahubNode function calls. diff --git a/changelog/64.fixed.md b/changelog/64.fixed.md new file mode 100644 index 00000000..06a070c6 --- /dev/null +++ b/changelog/64.fixed.md @@ -0,0 +1 @@ +Fix SDK playback hash generation to read the correct filename diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..2661297e --- /dev/null +++ b/codecov.yml @@ -0,0 +1,17 @@ +--- +coverage: + status: + project: + default: + target: 0% + # Set the threshold to allow a decrease of up to 5% without failing the PR + threshold: 5% + patch: + default: + target: 0% + # Set the threshold to allow a decrease of up to 5% in patch coverage without failing the PR + threshold: 5% + +comment: + layout: "header, diff, flags, files" + behavior: default diff --git a/infrahub_sdk/__init__.py b/infrahub_sdk/__init__.py index 624f7ee0..9892430a 100644 --- a/infrahub_sdk/__init__.py +++ b/infrahub_sdk/__init__.py @@ -2,76 +2,16 @@ import importlib.metadata -from infrahub_sdk.analyzer import GraphQLOperation, GraphQLQueryAnalyzer, GraphQLQueryVariable -from infrahub_sdk.batch import InfrahubBatch -from infrahub_sdk.branch import InfrahubBranchManager, InfrahubBranchManagerSync -from infrahub_sdk.client import InfrahubClient, InfrahubClientSync -from infrahub_sdk.config import Config -from infrahub_sdk.exceptions import ( - AuthenticationError, - Error, - GraphQLError, - NodeNotFoundError, - ServerNotReachableError, - ServerNotResponsiveError, - ValidationError, -) -from infrahub_sdk.graphql import Mutation, Query -from infrahub_sdk.node import InfrahubNode, InfrahubNodeSync -from infrahub_sdk.schema import ( - AttributeSchema, - GenericSchema, - InfrahubRepositoryConfig, - InfrahubSchema, - MainSchemaTypes, - NodeSchema, - ProfileSchema, - RelationshipCardinality, - RelationshipKind, - RelationshipSchema, - SchemaRoot, -) -from infrahub_sdk.store import NodeStore, NodeStoreSync -from infrahub_sdk.timestamp import Timestamp -from infrahub_sdk.uuidt import UUIDT, generate_uuid +from .client import InfrahubClient, InfrahubClientSync +from .config import Config __all__ = [ - "AttributeSchema", - "AuthenticationError", "Config", - "Error", - "InfrahubBatch", - "InfrahubBranchManager", - "InfrahubBranchManagerSync", "InfrahubClient", "InfrahubClientSync", - "InfrahubNode", - "InfrahubNodeSync", - "InfrahubRepositoryConfig", - "InfrahubSchema", - "generate_uuid", - "GenericSchema", - "GraphQLQueryAnalyzer", - "GraphQLQueryVariable", - "GraphQLError", - "GraphQLOperation", - "MainSchemaTypes", - "NodeNotFoundError", - "NodeSchema", - "Mutation", - "NodeStore", - "NodeStoreSync", - "ProfileSchema", - "Query", - "RelationshipSchema", - "RelationshipCardinality", - "RelationshipKind", - "SchemaRoot", - "ServerNotReachableError", - "ServerNotResponsiveError", - "Timestamp", - "UUIDT", - "ValidationError", ] -__version__ = importlib.metadata.version("infrahub-sdk") +try: + __version__ = importlib.metadata.version("infrahub-sdk") +except importlib.metadata.PackageNotFoundError: + __version__ = importlib.metadata.version("infrahub-server") diff --git a/infrahub_sdk/_importer.py b/infrahub_sdk/_importer.py index e4305b49..8d01adc7 100644 --- a/infrahub_sdk/_importer.py +++ b/infrahub_sdk/_importer.py @@ -4,7 +4,7 @@ import sys from typing import TYPE_CHECKING, Optional -from infrahub_sdk.exceptions import ModuleImportError +from .exceptions import ModuleImportError if TYPE_CHECKING: from pathlib import Path @@ -27,7 +27,7 @@ def import_module( try: module = importlib.import_module(module_name) except ModuleNotFoundError as exc: - raise ModuleImportError(message=f"{str(exc)} ({module_path})") from exc + raise ModuleImportError(message=f"{exc!s} ({module_path})") from exc except SyntaxError as exc: raise ModuleImportError(message=str(exc)) from exc diff --git a/infrahub_sdk/analyzer.py b/infrahub_sdk/analyzer.py index defcfff2..89f4e7ef 100644 --- a/infrahub_sdk/analyzer.py +++ b/infrahub_sdk/analyzer.py @@ -12,7 +12,7 @@ ) from pydantic import BaseModel -from infrahub_sdk.utils import calculate_dict_depth, calculate_dict_height, extract_fields +from .utils import calculate_dict_depth, calculate_dict_height, extract_fields class GraphQLQueryVariable(BaseModel): diff --git a/infrahub_sdk/batch.py b/infrahub_sdk/batch.py index 6cfd8f43..9e447dd7 100644 --- a/infrahub_sdk/batch.py +++ b/infrahub_sdk/batch.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from typing import Any, AsyncGenerator, Awaitable, Callable, Optional -from infrahub_sdk.node import InfrahubNode +from .node import InfrahubNode @dataclass diff --git a/infrahub_sdk/branch.py b/infrahub_sdk/branch.py index 131c5011..f23bc8e2 100644 --- a/infrahub_sdk/branch.py +++ b/infrahub_sdk/branch.py @@ -4,12 +4,12 @@ from pydantic import BaseModel -from infrahub_sdk.exceptions import BranchNotFoundError -from infrahub_sdk.graphql import Mutation, Query -from infrahub_sdk.utils import decode_json +from .exceptions import BranchNotFoundError +from .graphql import Mutation, Query +from .utils import decode_json if TYPE_CHECKING: - from infrahub_sdk.client import InfrahubClient, InfrahubClientSync + from .client import InfrahubClient, InfrahubClientSync class BranchData(BaseModel): diff --git a/infrahub_sdk/checks.py b/infrahub_sdk/checks.py index 4d869c1c..a873893c 100644 --- a/infrahub_sdk/checks.py +++ b/infrahub_sdk/checks.py @@ -10,13 +10,13 @@ from git.repo import Repo from pydantic import BaseModel, Field -from infrahub_sdk import InfrahubClient -from infrahub_sdk.exceptions import InfrahubCheckNotFoundError +from . import InfrahubClient +from .exceptions import InfrahubCheckNotFoundError, UninitializedError if TYPE_CHECKING: from pathlib import Path - from infrahub_sdk.schema import InfrahubCheckDefinitionConfig + from .schema import InfrahubCheckDefinitionConfig INFRAHUB_CHECK_VARIABLE_TO_IMPORT = "INFRAHUB_CHECKS" @@ -41,6 +41,7 @@ def __init__( output: Optional[str] = None, initializer: Optional[InfrahubCheckInitializer] = None, params: Optional[dict] = None, + client: Optional[InfrahubClient] = None, ): self.git: Optional[Repo] = None self.initializer = initializer or InfrahubCheckInitializer() @@ -55,7 +56,7 @@ def __init__( self.root_directory = root_directory or os.getcwd() - self.client: InfrahubClient + self._client = client if not self.name: self.name = self.__class__.__name__ @@ -66,6 +67,17 @@ def __init__( def __str__(self) -> str: return self.__class__.__name__ + @property + def client(self) -> InfrahubClient: + if self._client: + return self._client + + raise UninitializedError(message="This check has not been initialized with a client") + + @client.setter + def client(self, value: InfrahubClient) -> None: + self._client = value + @classmethod async def init(cls, client: Optional[InfrahubClient] = None, *args: Any, **kwargs: Any) -> InfrahubCheck: """Async init method, If an existing InfrahubClient client hasn't been provided, one will be created automatically.""" diff --git a/infrahub_sdk/client.py b/infrahub_sdk/client.py index 29310ac3..9d7dbeb2 100644 --- a/infrahub_sdk/client.py +++ b/infrahub_sdk/client.py @@ -23,17 +23,17 @@ import ujson from typing_extensions import Self -from infrahub_sdk.batch import InfrahubBatch -from infrahub_sdk.branch import ( +from .batch import InfrahubBatch +from .branch import ( BranchData, InfrahubBranchManager, InfrahubBranchManagerSync, ) -from infrahub_sdk.config import Config -from infrahub_sdk.constants import InfrahubClientMode -from infrahub_sdk.data import RepositoryBranchInfo, RepositoryData -from infrahub_sdk.diff import NodeDiff, diff_tree_node_to_node_diff, get_diff_summary_query -from infrahub_sdk.exceptions import ( +from .config import Config +from .constants import InfrahubClientMode +from .data import RepositoryBranchInfo, RepositoryData +from .diff import NodeDiff, diff_tree_node_to_node_diff, get_diff_summary_query +from .exceptions import ( AuthenticationError, Error, GraphQLError, @@ -41,20 +41,20 @@ ServerNotReachableError, ServerNotResponsiveError, ) -from infrahub_sdk.graphql import Mutation, Query -from infrahub_sdk.node import ( +from .graphql import Mutation, Query +from .node import ( InfrahubNode, InfrahubNodeSync, ) -from infrahub_sdk.object_store import ObjectStore, ObjectStoreSync -from infrahub_sdk.protocols_base import CoreNode, CoreNodeSync -from infrahub_sdk.queries import get_commit_update_mutation -from infrahub_sdk.query_groups import InfrahubGroupContext, InfrahubGroupContextSync -from infrahub_sdk.schema import InfrahubSchema, InfrahubSchemaSync, NodeSchema -from infrahub_sdk.store import NodeStore, NodeStoreSync -from infrahub_sdk.timestamp import Timestamp -from infrahub_sdk.types import AsyncRequester, HTTPMethod, SyncRequester -from infrahub_sdk.utils import decode_json, is_valid_uuid +from .object_store import ObjectStore, ObjectStoreSync +from .protocols_base import CoreNode, CoreNodeSync +from .queries import get_commit_update_mutation +from .query_groups import InfrahubGroupContext, InfrahubGroupContextSync +from .schema import InfrahubSchema, InfrahubSchemaSync, NodeSchema +from .store import NodeStore, NodeStoreSync +from .timestamp import Timestamp +from .types import AsyncRequester, HTTPMethod, SyncRequester +from .utils import decode_json, is_valid_uuid if TYPE_CHECKING: from types import TracebackType @@ -299,11 +299,12 @@ async def create( kind: Union[str, type[SchemaType]], data: Optional[dict] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, **kwargs: Any, ) -> Union[InfrahubNode, SchemaType]: branch = branch or self.default_branch - schema = await self.schema.get(kind=kind, branch=branch) + schema = await self.schema.get(kind=kind, branch=branch, timeout=timeout) if not data and not kwargs: raise ValueError("Either data or a list of keywords but be provided") @@ -324,6 +325,7 @@ async def get( raise_when_missing: Literal[False], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -341,6 +343,7 @@ async def get( raise_when_missing: Literal[True], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -358,6 +361,7 @@ async def get( raise_when_missing: bool = ..., at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -375,6 +379,7 @@ async def get( raise_when_missing: Literal[False], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -392,6 +397,7 @@ async def get( raise_when_missing: Literal[True], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -409,6 +415,7 @@ async def get( raise_when_missing: bool = ..., at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -425,6 +432,7 @@ async def get( raise_when_missing: bool = True, at: Optional[Timestamp] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, id: Optional[str] = None, hfid: Optional[list[str]] = None, include: Optional[list[str]] = None, @@ -458,6 +466,7 @@ async def get( kind=kind, at=at, branch=branch, + timeout=timeout, populate_store=populate_store, include=include, exclude=exclude, @@ -476,7 +485,12 @@ async def get( return results[0] async def _process_nodes_and_relationships( - self, response: dict[str, Any], schema_kind: str, branch: str, prefetch_relationships: bool + self, + response: dict[str, Any], + schema_kind: str, + branch: str, + prefetch_relationships: bool, + timeout: Optional[int] = None, ) -> ProcessRelationsNode: """Processes InfrahubNode and their Relationships from the GraphQL query response. @@ -485,6 +499,7 @@ async def _process_nodes_and_relationships( schema_kind (str): The kind of schema being queried. branch (str): The branch name. prefetch_relationships (bool): Flag to indicate whether to prefetch relationship data. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. Returns: ProcessRelationsNodeSync: A TypedDict containing two lists: @@ -496,11 +511,13 @@ async def _process_nodes_and_relationships( related_nodes: list[InfrahubNode] = [] for item in response.get(schema_kind, {}).get("edges", []): - node = await InfrahubNode.from_graphql(client=self, branch=branch, data=item) + node = await InfrahubNode.from_graphql(client=self, branch=branch, data=item, timeout=timeout) nodes.append(node) if prefetch_relationships: - await node._process_relationships(node_data=item, branch=branch, related_nodes=related_nodes) + await node._process_relationships( + node_data=item, branch=branch, related_nodes=related_nodes, timeout=timeout + ) return ProcessRelationsNode(nodes=nodes, related_nodes=related_nodes) @@ -510,6 +527,7 @@ async def all( kind: type[SchemaType], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -525,6 +543,7 @@ async def all( kind: str, at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -539,6 +558,7 @@ async def all( kind: Union[str, type[SchemaType]], at: Optional[Timestamp] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, populate_store: bool = False, offset: Optional[int] = None, limit: Optional[int] = None, @@ -554,6 +574,7 @@ async def all( at (Timestamp, optional): Time of the query. Defaults to Now. branch (str, optional): Name of the branch to query from. Defaults to default_branch. populate_store (bool, optional): Flag to indicate whether to populate the store with the retrieved nodes. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. offset (int, optional): The offset for pagination. limit (int, optional): The limit for pagination. include (list[str], optional): List of attributes or relationships to include in the query. @@ -568,6 +589,7 @@ async def all( kind=kind, at=at, branch=branch, + timeout=timeout, populate_store=populate_store, offset=offset, limit=limit, @@ -583,6 +605,7 @@ async def filters( kind: type[SchemaType], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -600,6 +623,7 @@ async def filters( kind: str, at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -616,6 +640,7 @@ async def filters( kind: Union[str, type[SchemaType]], at: Optional[Timestamp] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, populate_store: bool = False, offset: Optional[int] = None, limit: Optional[int] = None, @@ -632,6 +657,7 @@ async def filters( kind (str): kind of the nodes to query at (Timestamp, optional): Time of the query. Defaults to Now. branch (str, optional): Name of the branch to query from. Defaults to default_branch. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. populate_store (bool, optional): Flag to indicate whether to populate the store with the retrieved nodes. offset (int, optional): The offset for pagination. limit (int, optional): The limit for pagination. @@ -679,10 +705,15 @@ async def filters( branch_name=branch, at=at, tracker=f"query-{str(schema.kind).lower()}-page{page_number}", + timeout=timeout, ) process_result: ProcessRelationsNode = await self._process_nodes_and_relationships( - response=response, schema_kind=schema.kind, branch=branch, prefetch_relationships=prefetch_relationships + response=response, + schema_kind=schema.kind, + branch=branch, + prefetch_relationships=prefetch_relationships, + timeout=timeout, ) nodes.extend(process_result["nodes"]) related_nodes.extend(process_result["related_nodes"]) @@ -1400,10 +1431,11 @@ def create( kind: Union[str, type[SchemaTypeSync]], data: Optional[dict] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, **kwargs: Any, ) -> Union[InfrahubNodeSync, SchemaTypeSync]: branch = branch or self.default_branch - schema = self.schema.get(kind=kind, branch=branch) + schema = self.schema.get(kind=kind, branch=branch, timeout=timeout) if not data and not kwargs: raise ValueError("Either data or a list of keywords but be provided") @@ -1509,6 +1541,7 @@ def all( kind: type[SchemaTypeSync], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -1524,6 +1557,7 @@ def all( kind: str, at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -1538,6 +1572,7 @@ def all( kind: Union[str, type[SchemaTypeSync]], at: Optional[Timestamp] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, populate_store: bool = False, offset: Optional[int] = None, limit: Optional[int] = None, @@ -1552,6 +1587,7 @@ def all( kind (str): kind of the nodes to query at (Timestamp, optional): Time of the query. Defaults to Now. branch (str, optional): Name of the branch to query from. Defaults to default_branch. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. populate_store (bool, optional): Flag to indicate whether to populate the store with the retrieved nodes. offset (int, optional): The offset for pagination. limit (int, optional): The limit for pagination. @@ -1567,6 +1603,7 @@ def all( kind=kind, at=at, branch=branch, + timeout=timeout, populate_store=populate_store, offset=offset, limit=limit, @@ -1577,7 +1614,12 @@ def all( ) def _process_nodes_and_relationships( - self, response: dict[str, Any], schema_kind: str, branch: str, prefetch_relationships: bool + self, + response: dict[str, Any], + schema_kind: str, + branch: str, + prefetch_relationships: bool, + timeout: Optional[int] = None, ) -> ProcessRelationsNodeSync: """Processes InfrahubNodeSync and their Relationships from the GraphQL query response. @@ -1586,6 +1628,7 @@ def _process_nodes_and_relationships( schema_kind (str): The kind of schema being queried. branch (str): The branch name. prefetch_relationships (bool): Flag to indicate whether to prefetch relationship data. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. Returns: ProcessRelationsNodeSync: A TypedDict containing two lists: @@ -1597,11 +1640,11 @@ def _process_nodes_and_relationships( related_nodes: list[InfrahubNodeSync] = [] for item in response.get(schema_kind, {}).get("edges", []): - node = InfrahubNodeSync.from_graphql(client=self, branch=branch, data=item) + node = InfrahubNodeSync.from_graphql(client=self, branch=branch, data=item, timeout=timeout) nodes.append(node) if prefetch_relationships: - node._process_relationships(node_data=item, branch=branch, related_nodes=related_nodes) + node._process_relationships(node_data=item, branch=branch, related_nodes=related_nodes, timeout=timeout) return ProcessRelationsNodeSync(nodes=nodes, related_nodes=related_nodes) @@ -1611,6 +1654,7 @@ def filters( kind: type[SchemaTypeSync], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -1628,6 +1672,7 @@ def filters( kind: str, at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., populate_store: bool = ..., offset: Optional[int] = ..., limit: Optional[int] = ..., @@ -1644,6 +1689,7 @@ def filters( kind: Union[str, type[SchemaTypeSync]], at: Optional[Timestamp] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, populate_store: bool = False, offset: Optional[int] = None, limit: Optional[int] = None, @@ -1660,6 +1706,7 @@ def filters( kind (str): kind of the nodes to query at (Timestamp, optional): Time of the query. Defaults to Now. branch (str, optional): Name of the branch to query from. Defaults to default_branch. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. populate_store (bool, optional): Flag to indicate whether to populate the store with the retrieved nodes. offset (int, optional): The offset for pagination. limit (int, optional): The limit for pagination. @@ -1706,11 +1753,16 @@ def filters( query=query.render(), branch_name=branch, at=at, + timeout=timeout, tracker=f"query-{str(schema.kind).lower()}-page{page_number}", ) process_result: ProcessRelationsNodeSync = self._process_nodes_and_relationships( - response=response, schema_kind=schema.kind, branch=branch, prefetch_relationships=prefetch_relationships + response=response, + schema_kind=schema.kind, + branch=branch, + prefetch_relationships=prefetch_relationships, + timeout=timeout, ) nodes.extend(process_result["nodes"]) related_nodes.extend(process_result["related_nodes"]) @@ -1739,6 +1791,7 @@ def get( raise_when_missing: Literal[False], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -1756,6 +1809,7 @@ def get( raise_when_missing: Literal[True], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -1773,6 +1827,7 @@ def get( raise_when_missing: bool = ..., at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -1790,6 +1845,7 @@ def get( raise_when_missing: Literal[False], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -1807,6 +1863,7 @@ def get( raise_when_missing: Literal[True], at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -1824,6 +1881,7 @@ def get( raise_when_missing: bool = ..., at: Optional[Timestamp] = ..., branch: Optional[str] = ..., + timeout: Optional[int] = ..., id: Optional[str] = ..., hfid: Optional[list[str]] = ..., include: Optional[list[str]] = ..., @@ -1840,6 +1898,7 @@ def get( raise_when_missing: bool = True, at: Optional[Timestamp] = None, branch: Optional[str] = None, + timeout: Optional[int] = None, id: Optional[str] = None, hfid: Optional[list[str]] = None, include: Optional[list[str]] = None, @@ -1873,6 +1932,7 @@ def get( kind=kind, at=at, branch=branch, + timeout=timeout, populate_store=populate_store, include=include, exclude=exclude, diff --git a/infrahub_sdk/code_generator.py b/infrahub_sdk/code_generator.py index a56e2743..e0cc8326 100644 --- a/infrahub_sdk/code_generator.py +++ b/infrahub_sdk/code_generator.py @@ -2,9 +2,9 @@ import jinja2 -from infrahub_sdk import protocols as sdk_protocols -from infrahub_sdk.ctl.constants import PROTOCOLS_TEMPLATE -from infrahub_sdk.schema import ( +from . import protocols as sdk_protocols +from .ctl.constants import PROTOCOLS_TEMPLATE +from .schema import ( AttributeSchema, GenericSchema, MainSchemaTypes, diff --git a/infrahub_sdk/config.py b/infrahub_sdk/config.py index d0ce48de..02c1544f 100644 --- a/infrahub_sdk/config.py +++ b/infrahub_sdk/config.py @@ -4,11 +4,11 @@ from pydantic_settings import BaseSettings, SettingsConfigDict from typing_extensions import Self -from infrahub_sdk.constants import InfrahubClientMode -from infrahub_sdk.playback import JSONPlayback -from infrahub_sdk.recorder import JSONRecorder, NoRecorder, Recorder, RecorderType -from infrahub_sdk.types import AsyncRequester, InfrahubLoggers, RequesterTransport, SyncRequester -from infrahub_sdk.utils import get_branch, is_valid_url +from .constants import InfrahubClientMode +from .playback import JSONPlayback +from .recorder import JSONRecorder, NoRecorder, Recorder, RecorderType +from .types import AsyncRequester, InfrahubLoggers, RequesterTransport, SyncRequester +from .utils import get_branch, is_valid_url class ProxyMountsConfig(BaseSettings): @@ -54,7 +54,7 @@ class ConfigBase(BaseSettings): pagination_size: int = Field(default=50, description="Page size for queries to the server") retry_delay: int = Field(default=5, description="Number of seconds to wait until attempting a retry.") retry_on_failure: bool = Field(default=False, description="Retry operation in case of failure") - timeout: int = Field(default=10, description="Default connection timeout in seconds") + timeout: int = Field(default=60, description="Default connection timeout in seconds") transport: RequesterTransport = Field( default=RequesterTransport.HTTPX, description="Set an alternate transport using a predefined option" ) diff --git a/infrahub_sdk/ctl/_file.py b/infrahub_sdk/ctl/_file.py new file mode 100644 index 00000000..96629d72 --- /dev/null +++ b/infrahub_sdk/ctl/_file.py @@ -0,0 +1,13 @@ +from pathlib import Path + +from .exceptions import FileNotValidError + + +def read_file(file_name: Path) -> str: + if not file_name.is_file(): + raise FileNotValidError(name=str(file_name), message=f"{file_name} is not a valid file") + try: + with Path.open(file_name, encoding="utf-8") as fobj: + return fobj.read() + except UnicodeDecodeError as exc: + raise FileNotValidError(name=str(file_name), message=f"Unable to read {file_name} with utf-8 encoding") from exc diff --git a/infrahub_sdk/ctl/branch.py b/infrahub_sdk/ctl/branch.py index bc7013df..eba38419 100644 --- a/infrahub_sdk/ctl/branch.py +++ b/infrahub_sdk/ctl/branch.py @@ -4,10 +4,9 @@ from rich.console import Console from rich.table import Table -from infrahub_sdk.async_typer import AsyncTyper -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.ctl.utils import calculate_time_diff, catch_exception - +from ..async_typer import AsyncTyper +from ..ctl.client import initialize_client +from ..ctl.utils import calculate_time_diff, catch_exception from .parameters import CONFIG_PARAM app = AsyncTyper() diff --git a/infrahub_sdk/ctl/check.py b/infrahub_sdk/ctl/check.py index f9a131ed..99c547fe 100644 --- a/infrahub_sdk/ctl/check.py +++ b/infrahub_sdk/ctl/check.py @@ -11,14 +11,14 @@ from rich.console import Console from rich.logging import RichHandler -from infrahub_sdk import InfrahubClient -from infrahub_sdk.checks import InfrahubCheck -from infrahub_sdk.ctl import config -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.ctl.exceptions import QueryNotFoundError -from infrahub_sdk.ctl.repository import get_repository_config -from infrahub_sdk.ctl.utils import catch_exception, execute_graphql_query -from infrahub_sdk.schema import InfrahubCheckDefinitionConfig, InfrahubRepositoryConfig +from .. import InfrahubClient +from ..checks import InfrahubCheck +from ..ctl import config +from ..ctl.client import initialize_client +from ..ctl.exceptions import QueryNotFoundError +from ..ctl.repository import get_repository_config +from ..ctl.utils import catch_exception, execute_graphql_query +from ..schema import InfrahubCheckDefinitionConfig, InfrahubRepositoryConfig app = typer.Typer() console = Console() @@ -123,7 +123,7 @@ async def run_check( log.error(f" {log_message['message']}") except QueryNotFoundError as exc: - log.warning(f"{module_name}::{check}: unable to find query ({str(exc)})") + log.warning(f"{module_name}::{check}: unable to find query ({exc!s})") passed = False except Exception as exc: # pylint: disable=broad-exception-caught log.warning(f"{module_name}::{check}: An error occurred during execution ({exc})") @@ -196,7 +196,7 @@ async def run_checks( log = logging.getLogger("infrahub") check_summary: list[bool] = [] - client = await initialize_client() + client = initialize_client() for check_module in check_modules: if check_module.definition.targets: result = await run_targeted_check( diff --git a/infrahub_sdk/ctl/cli_commands.py b/infrahub_sdk/ctl/cli_commands.py index 712118af..324ba6ab 100644 --- a/infrahub_sdk/ctl/cli_commands.py +++ b/infrahub_sdk/ctl/cli_commands.py @@ -13,33 +13,39 @@ from rich.logging import RichHandler from rich.traceback import Traceback -from infrahub_sdk import __version__ as sdk_version -from infrahub_sdk.async_typer import AsyncTyper -from infrahub_sdk.code_generator import CodeGenerator -from infrahub_sdk.ctl import config -from infrahub_sdk.ctl.branch import app as branch_app -from infrahub_sdk.ctl.check import run as run_check -from infrahub_sdk.ctl.client import initialize_client, initialize_client_sync -from infrahub_sdk.ctl.exceptions import QueryNotFoundError -from infrahub_sdk.ctl.generator import run as run_generator -from infrahub_sdk.ctl.render import list_jinja2_transforms -from infrahub_sdk.ctl.repository import app as repository_app -from infrahub_sdk.ctl.repository import get_repository_config -from infrahub_sdk.ctl.schema import app as schema_app -from infrahub_sdk.ctl.schema import load_schemas_from_disk_and_exit -from infrahub_sdk.ctl.transform import list_transforms -from infrahub_sdk.ctl.utils import catch_exception, execute_graphql_query, parse_cli_vars -from infrahub_sdk.ctl.validate import app as validate_app -from infrahub_sdk.exceptions import GraphQLError, InfrahubTransformNotFoundError -from infrahub_sdk.jinja2 import identify_faulty_jinja_code -from infrahub_sdk.schema import ( +from .. import __version__ as sdk_version +from ..async_typer import AsyncTyper +from ..code_generator import CodeGenerator +from ..ctl import config +from ..ctl.branch import app as branch_app +from ..ctl.check import run as run_check +from ..ctl.client import initialize_client, initialize_client_sync +from ..ctl.exceptions import QueryNotFoundError +from ..ctl.generator import run as run_generator +from ..ctl.menu import app as menu_app +from ..ctl.object import app as object_app +from ..ctl.render import list_jinja2_transforms +from ..ctl.repository import app as repository_app +from ..ctl.repository import get_repository_config +from ..ctl.schema import app as schema_app +from ..ctl.transform import list_transforms +from ..ctl.utils import ( + catch_exception, + execute_graphql_query, + load_yamlfile_from_disk_and_exit, + parse_cli_vars, +) +from ..ctl.validate import app as validate_app +from ..exceptions import GraphQLError, InfrahubTransformNotFoundError +from ..jinja2 import identify_faulty_jinja_code +from ..schema import ( InfrahubRepositoryConfig, MainSchemaTypes, SchemaRoot, ) -from infrahub_sdk.transforms import get_transform_class_instance -from infrahub_sdk.utils import get_branch, write_to_file - +from ..transforms import get_transform_class_instance +from ..utils import get_branch, write_to_file +from ..yaml import SchemaFile from .exporter import dump from .importer import load from .parameters import CONFIG_PARAM @@ -50,6 +56,9 @@ app.add_typer(schema_app, name="schema") app.add_typer(validate_app, name="validate") app.add_typer(repository_app, name="repository") +app.add_typer(menu_app, name="menu") +app.add_typer(object_app, name="object", hidden=True) + app.command(name="dump")(dump) app.command(name="load")(load) @@ -197,7 +206,7 @@ def _run_transform( branch: str, debug: bool, repository_config: InfrahubRepositoryConfig, -): +) -> Any: """ Query GraphQL for the required data then run a transform on that data. @@ -357,7 +366,7 @@ def transform( @app.command(name="protocols") @catch_exception(console=console) -def protocols( # noqa: PLR0915 +def protocols( schemas: list[Path] = typer.Option(None, help="List of schemas or directory to load."), branch: str = typer.Option(None, help="Branch of schema to export Python protocols for."), sync: bool = typer.Option(False, help="Generate for sync or async."), @@ -369,11 +378,12 @@ def protocols( # noqa: PLR0915 schema: dict[str, MainSchemaTypes] = {} if schemas: - schemas_data = load_schemas_from_disk_and_exit(schemas=schemas) + schemas_data = load_yamlfile_from_disk_and_exit(paths=schemas, file_type=SchemaFile, console=console) for data in schemas_data: data.load_content() - schema_root = SchemaRoot(**data.content) + schema_root_data = data.content or {} + schema_root = SchemaRoot(**schema_root_data) schema.update({item.kind: item for item in schema_root.nodes + schema_root.generics}) else: @@ -392,7 +402,7 @@ def protocols( # noqa: PLR0915 @app.command(name="version") @catch_exception(console=console) -def version(_: str = CONFIG_PARAM): +def version(_: str = CONFIG_PARAM) -> None: """Display the version of Infrahub and the version of the Python SDK in use.""" client = initialize_client_sync() diff --git a/infrahub_sdk/ctl/client.py b/infrahub_sdk/ctl/client.py index 5699ec47..1285fb33 100644 --- a/infrahub_sdk/ctl/client.py +++ b/infrahub_sdk/ctl/client.py @@ -1,8 +1,8 @@ from typing import Any, Optional -from infrahub_sdk import InfrahubClient, InfrahubClientSync -from infrahub_sdk.config import Config -from infrahub_sdk.ctl import config +from .. import InfrahubClient, InfrahubClientSync +from ..config import Config +from ..ctl import config def initialize_client( diff --git a/infrahub_sdk/ctl/exporter.py b/infrahub_sdk/ctl/exporter.py index a292f23c..c94da8c9 100644 --- a/infrahub_sdk/ctl/exporter.py +++ b/infrahub_sdk/ctl/exporter.py @@ -6,14 +6,13 @@ import typer from rich.console import Console -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.transfer.exceptions import TransferError -from infrahub_sdk.transfer.exporter.json import LineDelimitedJSONExporter - +from ..ctl.client import initialize_client +from ..transfer.exceptions import TransferError +from ..transfer.exporter.json import LineDelimitedJSONExporter from .parameters import CONFIG_PARAM -def directory_name_with_timestamp(): +def directory_name_with_timestamp() -> str: right_now = datetime.now(timezone.utc).astimezone() timestamp = right_now.strftime("%Y%m%d-%H%M%S") return f"infrahubexport-{timestamp}" @@ -39,9 +38,10 @@ def dump( """Export nodes and their relationships out of the database.""" console = Console() - client = aiorun( - initialize_client(branch=branch, timeout=timeout, max_concurrent_execution=concurrent, retry_on_failure=True) + client = initialize_client( + branch=branch, timeout=timeout, max_concurrent_execution=concurrent, retry_on_failure=True ) + exporter = LineDelimitedJSONExporter(client, console=Console() if not quiet else None) try: aiorun(exporter.export(export_directory=directory, namespaces=namespace, branch=branch, exclude=exclude)) diff --git a/infrahub_sdk/ctl/generator.py b/infrahub_sdk/ctl/generator.py index a66ad206..26fd6db0 100644 --- a/infrahub_sdk/ctl/generator.py +++ b/infrahub_sdk/ctl/generator.py @@ -3,12 +3,12 @@ from rich.console import Console -from infrahub_sdk import InfrahubNode -from infrahub_sdk.ctl import config -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.ctl.repository import get_repository_config -from infrahub_sdk.ctl.utils import execute_graphql_query, parse_cli_vars -from infrahub_sdk.schema import InfrahubRepositoryConfig +from ..ctl import config +from ..ctl.client import initialize_client +from ..ctl.repository import get_repository_config +from ..ctl.utils import execute_graphql_query, parse_cli_vars +from ..node import InfrahubNode +from ..schema import InfrahubRepositoryConfig async def run( diff --git a/infrahub_sdk/ctl/importer.py b/infrahub_sdk/ctl/importer.py index b840f831..91d1e74d 100644 --- a/infrahub_sdk/ctl/importer.py +++ b/infrahub_sdk/ctl/importer.py @@ -4,15 +4,14 @@ import typer from rich.console import Console -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.transfer.exceptions import TransferError -from infrahub_sdk.transfer.importer.json import LineDelimitedJSONImporter -from infrahub_sdk.transfer.schema_sorter import InfrahubSchemaTopologicalSorter - +from ..ctl.client import initialize_client +from ..transfer.exceptions import TransferError +from ..transfer.importer.json import LineDelimitedJSONImporter +from ..transfer.schema_sorter import InfrahubSchemaTopologicalSorter from .parameters import CONFIG_PARAM -def local_directory(): +def local_directory() -> Path: # We use a function here to avoid failure when generating the documentation due to directory name return Path().resolve() @@ -35,9 +34,10 @@ def load( """Import nodes and their relationships into the database.""" console = Console() - client = aiorun( - initialize_client(branch=branch, timeout=timeout, max_concurrent_execution=concurrent, retry_on_failure=True) + client = initialize_client( + branch=branch, timeout=timeout, max_concurrent_execution=concurrent, retry_on_failure=True ) + importer = LineDelimitedJSONImporter( client, InfrahubSchemaTopologicalSorter(), diff --git a/infrahub_sdk/ctl/menu.py b/infrahub_sdk/ctl/menu.py new file mode 100644 index 00000000..fe9798fa --- /dev/null +++ b/infrahub_sdk/ctl/menu.py @@ -0,0 +1,54 @@ +import logging +from pathlib import Path + +import typer +from rich.console import Console + +from ..async_typer import AsyncTyper +from ..ctl.client import initialize_client +from ..ctl.utils import catch_exception, init_logging +from ..spec.menu import MenuFile +from .parameters import CONFIG_PARAM +from .utils import load_yamlfile_from_disk_and_exit + +app = AsyncTyper() +console = Console() + + +@app.callback() +def callback() -> None: + """ + Manage the menu in a remote Infrahub instance. + """ + + +@app.command() +@catch_exception(console=console) +async def load( + menus: list[Path], + debug: bool = False, + branch: str = typer.Option("main", help="Branch on which to load the menu."), + _: str = CONFIG_PARAM, +) -> None: + """Load one or multiple menu files into Infrahub.""" + + init_logging(debug=debug) + + logging.getLogger("infrahub_sdk").setLevel(logging.INFO) + + files = load_yamlfile_from_disk_and_exit(paths=menus, file_type=MenuFile, console=console) + client = initialize_client() + + for file in files: + file.validate_content() + schema = await client.schema.get(kind=file.spec.kind, branch=branch) + + for idx, item in enumerate(file.spec.data): + await file.spec.create_node( + client=client, + schema=schema, + data=item, + branch=branch, + default_schema_kind=file.spec.kind, + context={"list_index": idx}, + ) diff --git a/infrahub_sdk/ctl/object.py b/infrahub_sdk/ctl/object.py new file mode 100644 index 00000000..5f8e71cf --- /dev/null +++ b/infrahub_sdk/ctl/object.py @@ -0,0 +1,47 @@ +import logging +from pathlib import Path + +import typer +from rich.console import Console + +from ..async_typer import AsyncTyper +from ..ctl.client import initialize_client +from ..ctl.utils import catch_exception, init_logging +from ..spec.object import ObjectFile +from .parameters import CONFIG_PARAM +from .utils import load_yamlfile_from_disk_and_exit + +app = AsyncTyper() +console = Console() + + +@app.callback() +def callback() -> None: + """ + Manage objects in a remote Infrahub instance. + """ + + +@app.command() +@catch_exception(console=console) +async def load( + paths: list[Path], + debug: bool = False, + branch: str = typer.Option("main", help="Branch on which to load the objects."), + _: str = CONFIG_PARAM, +) -> None: + """Load one or multiple objects files into Infrahub.""" + + init_logging(debug=debug) + + logging.getLogger("infrahub_sdk").setLevel(logging.INFO) + + files = load_yamlfile_from_disk_and_exit(paths=paths, file_type=ObjectFile, console=console) + client = initialize_client() + + for file in files: + file.validate_content() + schema = await client.schema.get(kind=file.spec.kind, branch=branch) + + for item in file.spec.data: + await file.spec.create_node(client=client, schema=schema, data=item, branch=branch) diff --git a/infrahub_sdk/ctl/parameters.py b/infrahub_sdk/ctl/parameters.py index 740605e8..c1b7e5c2 100644 --- a/infrahub_sdk/ctl/parameters.py +++ b/infrahub_sdk/ctl/parameters.py @@ -1,6 +1,6 @@ import typer -from infrahub_sdk.ctl import config +from ..ctl import config def load_configuration(value: str) -> str: diff --git a/infrahub_sdk/ctl/repository.py b/infrahub_sdk/ctl/repository.py index 61ffeea9..8854e53b 100644 --- a/infrahub_sdk/ctl/repository.py +++ b/infrahub_sdk/ctl/repository.py @@ -5,13 +5,13 @@ from pydantic import ValidationError from rich.console import Console -from infrahub_sdk.async_typer import AsyncTyper -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.ctl.exceptions import FileNotValidError -from infrahub_sdk.ctl.utils import init_logging -from infrahub_sdk.graphql import Mutation -from infrahub_sdk.schema import InfrahubRepositoryConfig - +from ..async_typer import AsyncTyper +from ..ctl.client import initialize_client +from ..ctl.exceptions import FileNotValidError +from ..ctl.utils import init_logging +from ..graphql import Mutation +from ..schema import InfrahubRepositoryConfig +from ._file import read_file from .parameters import CONFIG_PARAM app = AsyncTyper() @@ -41,11 +41,9 @@ def get_repository_config(repo_config_file: Path) -> InfrahubRepositoryConfig: def load_repository_config_file(repo_config_file: Path) -> dict: - if not repo_config_file.is_file(): - raise FileNotFoundError(repo_config_file) + yaml_data = read_file(file_name=repo_config_file) try: - yaml_data = repo_config_file.read_text() data = yaml.safe_load(yaml_data) except yaml.YAMLError as exc: raise FileNotValidError(name=str(repo_config_file)) from exc diff --git a/infrahub_sdk/ctl/schema.py b/infrahub_sdk/ctl/schema.py index 9d7aa84f..697db621 100644 --- a/infrahub_sdk/ctl/schema.py +++ b/infrahub_sdk/ctl/schema.py @@ -8,16 +8,14 @@ from pydantic import ValidationError from rich.console import Console -from infrahub_sdk import InfrahubClient -from infrahub_sdk.async_typer import AsyncTyper -from infrahub_sdk.ctl.client import initialize_client -from infrahub_sdk.ctl.exceptions import FileNotValidError -from infrahub_sdk.ctl.utils import catch_exception, init_logging -from infrahub_sdk.queries import SCHEMA_HASH_SYNC_STATUS -from infrahub_sdk.utils import find_files -from infrahub_sdk.yaml import SchemaFile - +from .. import InfrahubClient +from ..async_typer import AsyncTyper +from ..ctl.client import initialize_client +from ..ctl.utils import catch_exception, init_logging +from ..queries import SCHEMA_HASH_SYNC_STATUS +from ..yaml import SchemaFile from .parameters import CONFIG_PARAM +from .utils import load_yamlfile_from_disk_and_exit app = AsyncTyper() console = Console() @@ -30,45 +28,6 @@ def callback() -> None: """ -def load_schemas_from_disk(schemas: list[Path]) -> list[SchemaFile]: - schemas_data: list[SchemaFile] = [] - for schema in schemas: - if schema.is_file(): - schema_file = SchemaFile(location=schema) - schema_file.load_content() - schemas_data.append(schema_file) - elif schema.is_dir(): - files = find_files(extension=["yaml", "yml", "json"], directory=schema) - for item in files: - schema_file = SchemaFile(location=item) - schema_file.load_content() - schemas_data.append(schema_file) - else: - raise FileNotValidError(name=schema, message=f"Schema path: {schema} does not exist!") - - return schemas_data - - -def load_schemas_from_disk_and_exit(schemas: list[Path]) -> list[SchemaFile]: - has_error = False - try: - schemas_data = load_schemas_from_disk(schemas=schemas) - except FileNotValidError as exc: - console.print(f"[red]{exc.message}") - raise typer.Exit(1) from exc - - for schema_file in schemas_data: - if schema_file.valid and schema_file.content: - continue - console.print(f"[red]{schema_file.error_message} ({schema_file.location})") - has_error = True - - if has_error: - raise typer.Exit(1) - - return schemas_data - - def validate_schema_content_and_exit(client: InfrahubClient, schemas: list[SchemaFile]) -> None: has_error: bool = False for schema_file in schemas: @@ -153,7 +112,7 @@ async def load( init_logging(debug=debug) - schemas_data = load_schemas_from_disk_and_exit(schemas=schemas) + schemas_data = load_yamlfile_from_disk_and_exit(paths=schemas, file_type=SchemaFile, console=console) schema_definition = "schema" if len(schemas_data) == 1 else "schemas" client = initialize_client() validate_schema_content_and_exit(client=client, schemas=schemas_data) @@ -203,7 +162,7 @@ async def check( init_logging(debug=debug) - schemas_data = load_schemas_from_disk_and_exit(schemas=schemas) + schemas_data = load_yamlfile_from_disk_and_exit(paths=schemas, file_type=SchemaFile, console=console) client = initialize_client() validate_schema_content_and_exit(client=client, schemas=schemas_data) diff --git a/infrahub_sdk/ctl/utils.py b/infrahub_sdk/ctl/utils.py index 73eb3e6d..43ae4d0e 100644 --- a/infrahub_sdk/ctl/utils.py +++ b/infrahub_sdk/ctl/utils.py @@ -3,7 +3,7 @@ import traceback from functools import wraps from pathlib import Path -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Coroutine, NoReturn, Optional, TypeVar, Union import pendulum import typer @@ -14,8 +14,8 @@ from rich.logging import RichHandler from rich.markup import escape -from infrahub_sdk.ctl.exceptions import QueryNotFoundError -from infrahub_sdk.exceptions import ( +from ..ctl.exceptions import FileNotValidError, QueryNotFoundError +from ..exceptions import ( AuthenticationError, Error, GraphQLError, @@ -24,10 +24,13 @@ ServerNotReachableError, ServerNotResponsiveError, ) -from infrahub_sdk.schema import InfrahubRepositoryConfig - +from ..schema import InfrahubRepositoryConfig +from ..yaml import YamlFile from .client import initialize_client_sync +YamlFileVar = TypeVar("YamlFileVar", bound=YamlFile) +T = TypeVar("T") + def init_logging(debug: bool = False) -> None: logging.getLogger("infrahub_sdk").setLevel(logging.CRITICAL) @@ -40,41 +43,43 @@ def init_logging(debug: bool = False) -> None: logging.getLogger("infrahubctl") -def handle_exception(exc: Exception, console: Console, exit_code: int): +def handle_exception(exc: Exception, console: Console, exit_code: int) -> NoReturn: """Handle exeception in a different fashion based on its type.""" if isinstance(exc, Exit): raise typer.Exit(code=exc.exit_code) if isinstance(exc, AuthenticationError): - console.print(f"[red]Authentication failure: {str(exc)}") + console.print(f"[red]Authentication failure: {exc!s}") raise typer.Exit(code=exit_code) if isinstance(exc, (ServerNotReachableError, ServerNotResponsiveError)): - console.print(f"[red]{str(exc)}") + console.print(f"[red]{exc!s}") raise typer.Exit(code=exit_code) if isinstance(exc, HTTPError): - console.print(f"[red]HTTP communication failure: {str(exc)} on {exc.request.method} to {exc.request.url}") + console.print(f"[red]HTTP communication failure: {exc!s} on {exc.request.method} to {exc.request.url}") raise typer.Exit(code=exit_code) if isinstance(exc, GraphQLError): print_graphql_errors(console=console, errors=exc.errors) raise typer.Exit(code=exit_code) if isinstance(exc, (SchemaNotFoundError, NodeNotFoundError)): - console.print(f"[red]Error: {str(exc)}") + console.print(f"[red]Error: {exc!s}") raise typer.Exit(code=exit_code) - console.print(f"[red]Error: {str(exc)}") + console.print(f"[red]Error: {exc!s}") console.print(traceback.format_exc()) raise typer.Exit(code=exit_code) -def catch_exception(console: Optional[Console] = None, exit_code: int = 1): +def catch_exception( + console: Optional[Console] = None, exit_code: int = 1 +) -> Callable[[Callable[..., T]], Callable[..., Union[T, Coroutine[Any, Any, T]]]]: """Decorator to handle exception for commands.""" if not console: console = Console() - def decorator(func: Callable): + def decorator(func: Callable[..., T]) -> Callable[..., Union[T, Coroutine[Any, Any, T]]]: if asyncio.iscoroutinefunction(func): @wraps(func) - async def async_wrapper(*args: Any, **kwargs: Any): + async def async_wrapper(*args: Any, **kwargs: Any) -> T: try: return await func(*args, **kwargs) except (Error, Exception) as exc: # pylint: disable=broad-exception-caught @@ -83,7 +88,7 @@ async def async_wrapper(*args: Any, **kwargs: Any): return async_wrapper @wraps(func) - def wrapper(*args: Any, **kwargs: Any): + def wrapper(*args: Any, **kwargs: Any) -> T: try: return func(*args, **kwargs) except (Error, Exception) as exc: # pylint: disable=broad-exception-caught @@ -114,8 +119,10 @@ def execute_graphql_query( ) if debug: - message = ("-" * 40, f"Response for GraphQL Query {query}", response, "-" * 40) - console.print("\n".join(message)) + console.print("-" * 40) + console.print(f"Response for GraphQL Query {query}") + console.print(response) + console.print("-" * 40) return response @@ -179,3 +186,25 @@ def get_fixtures_dir() -> Path: """Get the directory which stores fixtures that are common to multiple unit/integration tests.""" here = Path(__file__).resolve().parent return here.parent.parent / "tests" / "fixtures" + + +def load_yamlfile_from_disk_and_exit( + paths: list[Path], file_type: type[YamlFileVar], console: Console +) -> list[YamlFileVar]: + has_error = False + try: + data_files = file_type.load_from_disk(paths=paths) + except FileNotValidError as exc: + console.print(f"[red]{exc.message}") + raise typer.Exit(1) from exc + + for data_file in data_files: + if data_file.valid and data_file.content: + continue + console.print(f"[red]{data_file.error_message} ({data_file.location})") + has_error = True + + if has_error: + raise typer.Exit(1) + + return data_files diff --git a/infrahub_sdk/ctl/validate.py b/infrahub_sdk/ctl/validate.py index b4b593da..8b88b115 100644 --- a/infrahub_sdk/ctl/validate.py +++ b/infrahub_sdk/ctl/validate.py @@ -4,19 +4,18 @@ import typer import ujson -import yaml from pydantic import ValidationError from rich.console import Console -from ujson import JSONDecodeError - -from infrahub_sdk.async_typer import AsyncTyper -from infrahub_sdk.ctl.client import initialize_client, initialize_client_sync -from infrahub_sdk.ctl.exceptions import QueryNotFoundError -from infrahub_sdk.ctl.utils import catch_exception, find_graphql_query, parse_cli_vars -from infrahub_sdk.exceptions import GraphQLError -from infrahub_sdk.utils import get_branch, write_to_file +from ..async_typer import AsyncTyper +from ..ctl.client import initialize_client, initialize_client_sync +from ..ctl.exceptions import QueryNotFoundError +from ..ctl.utils import catch_exception, find_graphql_query, parse_cli_vars +from ..exceptions import GraphQLError +from ..utils import get_branch, write_to_file +from ..yaml import SchemaFile from .parameters import CONFIG_PARAM +from .utils import load_yamlfile_from_disk_and_exit app = AsyncTyper() console = Console() @@ -34,16 +33,15 @@ def callback() -> None: async def validate_schema(schema: Path, _: str = CONFIG_PARAM) -> None: """Validate the format of a schema file either in JSON or YAML""" - try: - schema_data = yaml.safe_load(schema.read_text()) or {} - except JSONDecodeError as exc: - console.print("[red]Invalid JSON file") - raise typer.Exit(1) from exc + schema_data = load_yamlfile_from_disk_and_exit(paths=[schema], file_type=SchemaFile, console=console) + if not schema_data: + console.print(f"[red]Unable to find {schema}") + raise typer.Exit(1) client = initialize_client() try: - client.schema.validate(schema_data) + client.schema.validate(schema_data[0].payload) except ValidationError as exc: console.print(f"[red]Schema not valid, found {len(exc.errors())} error(s)") for error in exc.errors(): diff --git a/infrahub_sdk/data.py b/infrahub_sdk/data.py index 6b831ed1..fc4af907 100644 --- a/infrahub_sdk/data.py +++ b/infrahub_sdk/data.py @@ -2,7 +2,7 @@ from pydantic import BaseModel, ConfigDict, Field -from infrahub_sdk.node import InfrahubNode +from .node import InfrahubNode class RepositoryBranchInfo(BaseModel): diff --git a/infrahub_sdk/generator.py b/infrahub_sdk/generator.py index 8e502a74..c7665fa6 100644 --- a/infrahub_sdk/generator.py +++ b/infrahub_sdk/generator.py @@ -6,12 +6,12 @@ from git.repo import Repo -from infrahub_sdk.exceptions import UninitializedError +from .exceptions import UninitializedError if TYPE_CHECKING: - from infrahub_sdk.client import InfrahubClient - from infrahub_sdk.node import InfrahubNode - from infrahub_sdk.store import NodeStore + from .client import InfrahubClient + from .node import InfrahubNode + from .store import NodeStore class InfrahubGenerator: diff --git a/infrahub_sdk/graphql.py b/infrahub_sdk/graphql.py index 2d1d9d19..fcda2a49 100644 --- a/infrahub_sdk/graphql.py +++ b/infrahub_sdk/graphql.py @@ -48,12 +48,12 @@ def render_query_block(data: dict, offset: int = 4, indentation: int = 4) -> lis elif isinstance(value, dict) and len(value) == 1 and ALIAS_KEY in value and value[ALIAS_KEY]: lines.append(f"{offset_str}{value[ALIAS_KEY]}: {key}") elif isinstance(value, dict): - if ALIAS_KEY in value and value[ALIAS_KEY]: + if value.get(ALIAS_KEY): key_str = f"{value[ALIAS_KEY]}: {key}" else: key_str = key - if FILTERS_KEY in value and value[FILTERS_KEY]: + if value.get(FILTERS_KEY): filters_str = ", ".join( [f"{key2}: {convert_to_graphql_as_string(value2)}" for key2, value2 in value[FILTERS_KEY].items()] ) diff --git a/infrahub_sdk/node.py b/infrahub_sdk/node.py index c3691f46..38fb6742 100644 --- a/infrahub_sdk/node.py +++ b/infrahub_sdk/node.py @@ -5,23 +5,23 @@ from copy import copy from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, Union, get_args -from infrahub_sdk.constants import InfrahubClientMode -from infrahub_sdk.exceptions import ( +from .constants import InfrahubClientMode +from .exceptions import ( Error, FeatureNotSupportedError, NodeNotFoundError, UninitializedError, ) -from infrahub_sdk.graphql import Mutation, Query -from infrahub_sdk.schema import GenericSchema, RelationshipCardinality, RelationshipKind -from infrahub_sdk.utils import compare_lists, get_flat_value -from infrahub_sdk.uuidt import UUIDT +from .graphql import Mutation, Query +from .schema import GenericSchema, RelationshipCardinality, RelationshipKind +from .utils import compare_lists, get_flat_value +from .uuidt import UUIDT if TYPE_CHECKING: from typing_extensions import Self - from infrahub_sdk.client import InfrahubClient, InfrahubClientSync - from infrahub_sdk.schema import AttributeSchema, MainSchemaTypes, RelationshipSchema + from .client import InfrahubClient, InfrahubClientSync + from .schema import AttributeSchema, MainSchemaTypes, RelationshipSchema # pylint: disable=too-many-lines @@ -314,11 +314,13 @@ def __init__( self._client = client super().__init__(branch=branch, schema=schema, data=data, name=name) - async def fetch(self) -> None: + async def fetch(self, timeout: Optional[int] = None) -> None: if not self.id or not self.typename: raise Error("Unable to fetch the peer, id and/or typename are not defined") - self._peer = await self._client.get(kind=self.typename, id=self.id, populate_store=True, branch=self._branch) + self._peer = await self._client.get( + kind=self.typename, id=self.id, populate_store=True, branch=self._branch, timeout=timeout + ) @property def peer(self) -> InfrahubNode: @@ -359,11 +361,13 @@ def __init__( self._client = client super().__init__(branch=branch, schema=schema, data=data, name=name) - def fetch(self) -> None: + def fetch(self, timeout: Optional[int] = None) -> None: if not self.id or not self.typename: raise Error("Unable to fetch the peer, id and/or typename are not defined") - self._peer = self._client.get(kind=self.typename, id=self.id, populate_store=True, branch=self._branch) + self._peer = self._client.get( + kind=self.typename, id=self.id, populate_store=True, branch=self._branch, timeout=timeout + ) @property def peer(self) -> InfrahubNodeSync: @@ -1045,13 +1049,18 @@ def __init__( @classmethod async def from_graphql( - cls, client: InfrahubClient, branch: str, data: dict, schema: Optional[MainSchemaTypes] = None + cls, + client: InfrahubClient, + branch: str, + data: dict, + schema: Optional[MainSchemaTypes] = None, + timeout: Optional[int] = None, ) -> Self: if not schema: node_kind = data.get("__typename", None) or data.get("node", {}).get("__typename", None) if not node_kind: raise ValueError("Unable to determine the type of the node, __typename not present in data") - schema = await client.schema.get(kind=node_kind, branch=branch) + schema = await client.schema.get(kind=node_kind, branch=branch, timeout=timeout) return cls(client=client, schema=schema, branch=branch, data=cls._strip_alias(data)) @@ -1065,7 +1074,7 @@ def _init_relationships(self, data: Optional[dict] = None) -> None: setattr( self.__class__, rel_name, - generate_relationship_property(name=rel_name, node=self, node_class=RelatedNode), # type: ignore[arg-type] + generate_relationship_property(name=rel_name, node=self), ) setattr(self, rel_name, rel_data) else: @@ -1104,7 +1113,7 @@ async def artifact_fetch(self, name: str) -> Union[str, dict[str, Any]]: content = await self._client.object_store.get(identifier=artifact.storage_id.value) # type: ignore[attr-defined] return content - async def delete(self) -> None: + async def delete(self, timeout: Optional[int] = None) -> None: input_data = {"data": {"id": self.id}} mutation_query = {"ok": None} query = Mutation( @@ -1115,14 +1124,17 @@ async def delete(self) -> None: await self._client.execute_graphql( query=query.render(), branch_name=self._branch, + timeout=timeout, tracker=f"mutation-{str(self._schema.kind).lower()}-delete", ) - async def save(self, allow_upsert: bool = False, update_group_context: Optional[bool] = None) -> None: + async def save( + self, allow_upsert: bool = False, update_group_context: Optional[bool] = None, timeout: Optional[int] = None + ) -> None: if self._existing is False or allow_upsert is True: - await self.create(allow_upsert=allow_upsert) + await self.create(allow_upsert=allow_upsert, timeout=timeout) else: - await self.update() + await self.update(timeout=timeout) if update_group_context is None and self._client.mode == InfrahubClientMode.TRACKING: update_group_context = True @@ -1297,7 +1309,9 @@ def _generate_mutation_query(self) -> dict[str, Any]: return query_result - async def _process_mutation_result(self, mutation_name: str, response: dict[str, Any]) -> None: + async def _process_mutation_result( + self, mutation_name: str, response: dict[str, Any], timeout: Optional[int] = None + ) -> None: object_response: dict[str, Any] = response[mutation_name]["object"] self.id = object_response["id"] self._existing = True @@ -1324,10 +1338,10 @@ async def _process_mutation_result(self, mutation_name: str, response: dict[str, related_node = RelatedNode( client=self._client, branch=self._branch, schema=rel.schema, data=allocated_resource ) - await related_node.fetch() + await related_node.fetch(timeout=timeout) setattr(self, rel_name, related_node) - async def create(self, allow_upsert: bool = False) -> None: + async def create(self, allow_upsert: bool = False, timeout: Optional[int] = None) -> None: mutation_query = self._generate_mutation_query() if allow_upsert: @@ -1345,11 +1359,15 @@ async def create(self, allow_upsert: bool = False) -> None: variables=input_data["mutation_variables"], ) response = await self._client.execute_graphql( - query=query.render(), branch_name=self._branch, tracker=tracker, variables=input_data["variables"] + query=query.render(), + branch_name=self._branch, + tracker=tracker, + variables=input_data["variables"], + timeout=timeout, ) - await self._process_mutation_result(mutation_name=mutation_name, response=response) + await self._process_mutation_result(mutation_name=mutation_name, response=response, timeout=timeout) - async def update(self, do_full_update: bool = False) -> None: + async def update(self, do_full_update: bool = False, timeout: Optional[int] = None) -> None: input_data = self._generate_input_data(exclude_unmodified=not do_full_update) mutation_query = self._generate_mutation_query() mutation_name = f"{self._schema.kind}Update" @@ -1363,13 +1381,14 @@ async def update(self, do_full_update: bool = False) -> None: response = await self._client.execute_graphql( query=query.render(), branch_name=self._branch, + timeout=timeout, tracker=f"mutation-{str(self._schema.kind).lower()}-update", variables=input_data["variables"], ) - await self._process_mutation_result(mutation_name=mutation_name, response=response) + await self._process_mutation_result(mutation_name=mutation_name, response=response, timeout=timeout) async def _process_relationships( - self, node_data: dict[str, Any], branch: str, related_nodes: list[InfrahubNode] + self, node_data: dict[str, Any], branch: str, related_nodes: list[InfrahubNode], timeout: Optional[int] = None ) -> None: """Processes the Relationships of a InfrahubNode and add Related Nodes to a list. @@ -1377,19 +1396,24 @@ async def _process_relationships( node_data (dict[str, Any]): The item from the GraphQL response corresponding to the node. branch (str): The branch name. related_nodes (list[InfrahubNode]): The list to which related nodes will be appended. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. """ for rel_name in self._relationships: rel = getattr(self, rel_name) if rel and isinstance(rel, RelatedNode): relation = node_data["node"].get(rel_name) if relation.get("node", None): - related_node = await InfrahubNode.from_graphql(client=self._client, branch=branch, data=relation) + related_node = await InfrahubNode.from_graphql( + client=self._client, branch=branch, data=relation, timeout=timeout + ) related_nodes.append(related_node) elif rel and isinstance(rel, RelationshipManager): peers = node_data["node"].get(rel_name) if peers: for peer in peers["edges"]: - related_node = await InfrahubNode.from_graphql(client=self._client, branch=branch, data=peer) + related_node = await InfrahubNode.from_graphql( + client=self._client, branch=branch, data=peer, timeout=timeout + ) related_nodes.append(related_node) async def get_pool_allocated_resources(self, resource: InfrahubNode) -> list[InfrahubNode]: @@ -1522,13 +1546,18 @@ def __init__( @classmethod def from_graphql( - cls, client: InfrahubClientSync, branch: str, data: dict, schema: Optional[MainSchemaTypes] = None + cls, + client: InfrahubClientSync, + branch: str, + data: dict, + schema: Optional[MainSchemaTypes] = None, + timeout: Optional[int] = None, ) -> Self: if not schema: node_kind = data.get("__typename", None) or data.get("node", {}).get("__typename", None) if not node_kind: raise ValueError("Unable to determine the type of the node, __typename not present in data") - schema = client.schema.get(kind=node_kind, branch=branch) + schema = client.schema.get(kind=node_kind, branch=branch, timeout=timeout) return cls(client=client, schema=schema, branch=branch, data=cls._strip_alias(data)) @@ -1542,7 +1571,7 @@ def _init_relationships(self, data: Optional[dict] = None) -> None: setattr( self.__class__, rel_name, - generate_relationship_property(name=rel_name, node=self, node_class=RelatedNodeSync), # type: ignore[arg-type] + generate_relationship_property(name=rel_name, node=self), ) setattr(self, rel_name, rel_data) else: @@ -1578,7 +1607,7 @@ def artifact_fetch(self, name: str) -> Union[str, dict[str, Any]]: content = self._client.object_store.get(identifier=artifact.storage_id.value) # type: ignore[attr-defined] return content - def delete(self) -> None: + def delete(self, timeout: Optional[int] = None) -> None: input_data = {"data": {"id": self.id}} mutation_query = {"ok": None} query = Mutation( @@ -1590,13 +1619,16 @@ def delete(self) -> None: query=query.render(), branch_name=self._branch, tracker=f"mutation-{str(self._schema.kind).lower()}-delete", + timeout=timeout, ) - def save(self, allow_upsert: bool = False, update_group_context: Optional[bool] = None) -> None: + def save( + self, allow_upsert: bool = False, update_group_context: Optional[bool] = None, timeout: Optional[int] = None + ) -> None: if self._existing is False or allow_upsert is True: - self.create(allow_upsert=allow_upsert) + self.create(allow_upsert=allow_upsert, timeout=timeout) else: - self.update() + self.update(timeout=timeout) if update_group_context is None and self._client.mode == InfrahubClientMode.TRACKING: update_group_context = True @@ -1770,7 +1802,9 @@ def _generate_mutation_query(self) -> dict[str, Any]: return query_result - def _process_mutation_result(self, mutation_name: str, response: dict[str, Any]) -> None: + def _process_mutation_result( + self, mutation_name: str, response: dict[str, Any], timeout: Optional[int] = None + ) -> None: object_response: dict[str, Any] = response[mutation_name]["object"] self.id = object_response["id"] self._existing = True @@ -1797,10 +1831,10 @@ def _process_mutation_result(self, mutation_name: str, response: dict[str, Any]) related_node = RelatedNodeSync( client=self._client, branch=self._branch, schema=rel.schema, data=allocated_resource ) - related_node.fetch() + related_node.fetch(timeout=timeout) setattr(self, rel_name, related_node) - def create(self, allow_upsert: bool = False) -> None: + def create(self, allow_upsert: bool = False, timeout: Optional[int] = None) -> None: mutation_query = self._generate_mutation_query() if allow_upsert: @@ -1819,11 +1853,15 @@ def create(self, allow_upsert: bool = False) -> None: ) response = self._client.execute_graphql( - query=query.render(), branch_name=self._branch, tracker=tracker, variables=input_data["variables"] + query=query.render(), + branch_name=self._branch, + tracker=tracker, + variables=input_data["variables"], + timeout=timeout, ) - self._process_mutation_result(mutation_name=mutation_name, response=response) + self._process_mutation_result(mutation_name=mutation_name, response=response, timeout=timeout) - def update(self, do_full_update: bool = False) -> None: + def update(self, do_full_update: bool = False, timeout: Optional[int] = None) -> None: input_data = self._generate_input_data(exclude_unmodified=not do_full_update) mutation_query = self._generate_mutation_query() mutation_name = f"{self._schema.kind}Update" @@ -1840,11 +1878,16 @@ def update(self, do_full_update: bool = False) -> None: branch_name=self._branch, tracker=f"mutation-{str(self._schema.kind).lower()}-update", variables=input_data["variables"], + timeout=timeout, ) - self._process_mutation_result(mutation_name=mutation_name, response=response) + self._process_mutation_result(mutation_name=mutation_name, response=response, timeout=timeout) def _process_relationships( - self, node_data: dict[str, Any], branch: str, related_nodes: list[InfrahubNodeSync] + self, + node_data: dict[str, Any], + branch: str, + related_nodes: list[InfrahubNodeSync], + timeout: Optional[int] = None, ) -> None: """Processes the Relationships of a InfrahubNodeSync and add Related Nodes to a list. @@ -1852,19 +1895,25 @@ def _process_relationships( node_data (dict[str, Any]): The item from the GraphQL response corresponding to the node. branch (str): The branch name. related_nodes (list[InfrahubNodeSync]): The list to which related nodes will be appended. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. + """ for rel_name in self._relationships: rel = getattr(self, rel_name) if rel and isinstance(rel, RelatedNodeSync): relation = node_data["node"].get(rel_name) if relation.get("node", None): - related_node = InfrahubNodeSync.from_graphql(client=self._client, branch=branch, data=relation) + related_node = InfrahubNodeSync.from_graphql( + client=self._client, branch=branch, data=relation, timeout=timeout + ) related_nodes.append(related_node) elif rel and isinstance(rel, RelationshipManagerSync): peers = node_data["node"].get(rel_name) if peers: for peer in peers["edges"]: - related_node = InfrahubNodeSync.from_graphql(client=self._client, branch=branch, data=peer) + related_node = InfrahubNodeSync.from_graphql( + client=self._client, branch=branch, data=peer, timeout=timeout + ) related_nodes.append(related_node) def get_pool_allocated_resources(self, resource: InfrahubNodeSync) -> list[InfrahubNodeSync]: @@ -1993,13 +2042,12 @@ def _generate_input_data(self) -> Union[str, None]: return self.id -def generate_relationship_property(node: Union[InfrahubNode, InfrahubNodeSync], name: str, node_class): # type: ignore +def generate_relationship_property(node: Union[InfrahubNode, InfrahubNodeSync], name: str) -> property: """Generates a property that stores values under a private non-public name. Args: node (Union[InfrahubNode, InfrahubNodeSync]): The node instance. name (str): The name of the relationship property. - node_class: The class of the node. Returns: A property object for managing the relationship. @@ -2008,20 +2056,29 @@ def generate_relationship_property(node: Union[InfrahubNode, InfrahubNodeSync], internal_name = "_" + name.lower() external_name = name - @property # type: ignore - def prop(self): # type: ignore + def prop_getter(self: InfrahubNodeBase) -> Any: return getattr(self, internal_name) - @prop.setter - def prop(self, value): # type: ignore + def prop_setter(self: InfrahubNodeBase, value: Any) -> None: if isinstance(value, RelatedNodeBase) or value is None: setattr(self, internal_name, value) else: schema = [rel for rel in self._schema.relationships if rel.name == external_name][0] - setattr( - self, - internal_name, - node_class(name=external_name, branch=node._branch, client=node._client, schema=schema, data=value), - ) + if isinstance(node, InfrahubNode): + setattr( + self, + internal_name, + RelatedNode( + name=external_name, branch=node._branch, client=node._client, schema=schema, data=value + ), + ) + else: + setattr( + self, + internal_name, + RelatedNodeSync( + name=external_name, branch=node._branch, client=node._client, schema=schema, data=value + ), + ) - return prop + return property(prop_getter, prop_setter) diff --git a/infrahub_sdk/object_store.py b/infrahub_sdk/object_store.py index 33a5c090..31034bfe 100644 --- a/infrahub_sdk/object_store.py +++ b/infrahub_sdk/object_store.py @@ -5,10 +5,10 @@ import httpx -from infrahub_sdk.exceptions import AuthenticationError, ServerNotReachableError +from .exceptions import AuthenticationError, ServerNotReachableError if TYPE_CHECKING: - from infrahub_sdk.client import InfrahubClient, InfrahubClientSync + from .client import InfrahubClient, InfrahubClientSync class ObjectStoreBase: diff --git a/infrahub_sdk/playback.py b/infrahub_sdk/playback.py index 72e65954..a8775dc7 100644 --- a/infrahub_sdk/playback.py +++ b/infrahub_sdk/playback.py @@ -1,3 +1,4 @@ +import json from pathlib import Path from typing import Any, Optional @@ -6,8 +7,8 @@ from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict -from infrahub_sdk.types import HTTPMethod -from infrahub_sdk.utils import generate_request_filename +from .types import HTTPMethod +from .utils import generate_request_filename class JSONPlayback(BaseSettings): @@ -44,7 +45,7 @@ def _read_request( ) -> httpx.Response: content: Optional[bytes] = None if payload: - content = str(ujson.dumps(payload)).encode("utf-8") + content = str(json.dumps(payload)).encode("UTF-8") request = httpx.Request(method=method.value, url=url, headers=headers, content=content) filename = generate_request_filename(request) diff --git a/infrahub_sdk/protocols.py b/infrahub_sdk/protocols.py index 048ec982..f187cc43 100644 --- a/infrahub_sdk/protocols.py +++ b/infrahub_sdk/protocols.py @@ -73,6 +73,8 @@ class CoreArtifactTarget(CoreNode): class CoreBasePermission(CoreNode): + decision: Enum + identifier: StringOptional roles: RelationshipManager @@ -137,6 +139,22 @@ class CoreGroup(CoreNode): children: RelationshipManager +class CoreMenu(CoreNode): + namespace: String + name: String + label: StringOptional + kind: StringOptional + path: StringOptional + description: StringOptional + icon: StringOptional + protected: Boolean + order_weight: Integer + required_permissions: ListAttributeOptional + section: Enum + parent: RelatedNode + children: RelationshipManager + + class CoreProfile(CoreNode): profile_name: String profile_priority: IntegerOptional @@ -369,6 +387,10 @@ class CoreIPPrefixPool(CoreResourcePool, LineageSource): ip_namespace: RelatedNode +class CoreMenuItem(CoreMenu): + pass + + class CoreNumberPool(CoreResourcePool, LineageSource): node: String node_attribute: String @@ -377,11 +399,9 @@ class CoreNumberPool(CoreResourcePool, LineageSource): class CoreObjectPermission(CoreBasePermission): - branch: String namespace: String name: String action: Enum - decision: Enum class CoreObjectThread(CoreThread): @@ -518,6 +538,8 @@ class CoreArtifactTargetSync(CoreNodeSync): class CoreBasePermissionSync(CoreNodeSync): + decision: Enum + identifier: StringOptional roles: RelationshipManagerSync @@ -582,6 +604,22 @@ class CoreGroupSync(CoreNodeSync): children: RelationshipManagerSync +class CoreMenuSync(CoreNodeSync): + namespace: String + name: String + label: StringOptional + kind: StringOptional + path: StringOptional + description: StringOptional + icon: StringOptional + protected: Boolean + order_weight: Integer + required_permissions: ListAttributeOptional + section: Enum + parent: RelatedNodeSync + children: RelationshipManagerSync + + class CoreProfileSync(CoreNodeSync): profile_name: String profile_priority: IntegerOptional @@ -814,6 +852,10 @@ class CoreIPPrefixPoolSync(CoreResourcePoolSync, LineageSourceSync): ip_namespace: RelatedNodeSync +class CoreMenuItemSync(CoreMenuSync): + pass + + class CoreNumberPoolSync(CoreResourcePoolSync, LineageSourceSync): node: String node_attribute: String @@ -822,11 +864,9 @@ class CoreNumberPoolSync(CoreResourcePoolSync, LineageSourceSync): class CoreObjectPermissionSync(CoreBasePermissionSync): - branch: String namespace: String name: String action: Enum - decision: Enum class CoreObjectThreadSync(CoreThreadSync): diff --git a/infrahub_sdk/protocols_base.py b/infrahub_sdk/protocols_base.py index 6bd0b3ad..df6a9000 100644 --- a/infrahub_sdk/protocols_base.py +++ b/infrahub_sdk/protocols_base.py @@ -5,7 +5,7 @@ if TYPE_CHECKING: import ipaddress - from infrahub_sdk.schema import MainSchemaTypes + from .schema import MainSchemaTypes @runtime_checkable diff --git a/infrahub_sdk/pytest_plugin/items/__init__.py b/infrahub_sdk/pytest_plugin/items/__init__.py index e75b2528..a923afb5 100644 --- a/infrahub_sdk/pytest_plugin/items/__init__.py +++ b/infrahub_sdk/pytest_plugin/items/__init__.py @@ -13,12 +13,12 @@ ) __all__ = [ - "InfrahubItem", "InfrahubCheckIntegrationItem", "InfrahubCheckSmokeItem", "InfrahubCheckUnitProcessItem", "InfrahubGraphQLQueryIntegrationItem", "InfrahubGraphQLQuerySmokeItem", + "InfrahubItem", "InfrahubJinja2TransformIntegrationItem", "InfrahubJinja2TransformSmokeItem", "InfrahubJinja2TransformUnitRenderItem", diff --git a/infrahub_sdk/pytest_plugin/items/base.py b/infrahub_sdk/pytest_plugin/items/base.py index 1b881798..1452737a 100644 --- a/infrahub_sdk/pytest_plugin/items/base.py +++ b/infrahub_sdk/pytest_plugin/items/base.py @@ -13,8 +13,7 @@ if TYPE_CHECKING: from pathlib import Path - from infrahub_sdk.schema import InfrahubRepositoryConfigElement - + from ...schema import InfrahubRepositoryConfigElement from ..models import InfrahubTest diff --git a/infrahub_sdk/pytest_plugin/items/check.py b/infrahub_sdk/pytest_plugin/items/check.py index 7cf230bd..dd4194f0 100644 --- a/infrahub_sdk/pytest_plugin/items/check.py +++ b/infrahub_sdk/pytest_plugin/items/check.py @@ -6,8 +6,7 @@ import ujson from httpx import HTTPStatusError -from infrahub_sdk.checks import get_check_class_instance - +from ...checks import get_check_class_instance from ..exceptions import CheckDefinitionError, CheckResultError from ..models import InfrahubTestExpectedResult from .base import InfrahubItem @@ -15,9 +14,9 @@ if TYPE_CHECKING: from pytest import ExceptionInfo - from infrahub_sdk.checks import InfrahubCheck - from infrahub_sdk.pytest_plugin.models import InfrahubTest - from infrahub_sdk.schema import InfrahubRepositoryConfigElement + from ...checks import InfrahubCheck + from ...schema import InfrahubRepositoryConfigElement + from ..models import InfrahubTest class InfrahubCheckItem(InfrahubItem): diff --git a/infrahub_sdk/pytest_plugin/items/graphql_query.py b/infrahub_sdk/pytest_plugin/items/graphql_query.py index abb048fb..d77fc9e7 100644 --- a/infrahub_sdk/pytest_plugin/items/graphql_query.py +++ b/infrahub_sdk/pytest_plugin/items/graphql_query.py @@ -5,8 +5,7 @@ import ujson from httpx import HTTPStatusError -from infrahub_sdk.analyzer import GraphQLQueryAnalyzer - +from ...analyzer import GraphQLQueryAnalyzer from ..exceptions import OutputMatchError from ..models import InfrahubTestExpectedResult from .base import InfrahubItem diff --git a/infrahub_sdk/pytest_plugin/items/python_transform.py b/infrahub_sdk/pytest_plugin/items/python_transform.py index 9a203665..6249d8ba 100644 --- a/infrahub_sdk/pytest_plugin/items/python_transform.py +++ b/infrahub_sdk/pytest_plugin/items/python_transform.py @@ -6,8 +6,7 @@ import ujson from httpx import HTTPStatusError -from infrahub_sdk.transforms import get_transform_class_instance - +from ...transforms import get_transform_class_instance from ..exceptions import OutputMatchError, PythonTransformDefinitionError from ..models import InfrahubTestExpectedResult from .base import InfrahubItem @@ -15,9 +14,9 @@ if TYPE_CHECKING: from pytest import ExceptionInfo - from infrahub_sdk.pytest_plugin.models import InfrahubTest - from infrahub_sdk.schema import InfrahubRepositoryConfigElement - from infrahub_sdk.transforms import InfrahubTransform + from ...schema import InfrahubRepositoryConfigElement + from ...transforms import InfrahubTransform + from ..models import InfrahubTest class InfrahubPythonTransformItem(InfrahubItem): diff --git a/infrahub_sdk/pytest_plugin/plugin.py b/infrahub_sdk/pytest_plugin/plugin.py index 08d355c1..98b864a7 100644 --- a/infrahub_sdk/pytest_plugin/plugin.py +++ b/infrahub_sdk/pytest_plugin/plugin.py @@ -5,9 +5,8 @@ from pytest import Collector, Config, Item, Parser, Session from pytest import exit as exit_test -from infrahub_sdk import InfrahubClientSync -from infrahub_sdk.utils import is_valid_url - +from .. import InfrahubClientSync +from ..utils import is_valid_url from .loader import InfrahubYamlFile from .utils import load_repository_config diff --git a/infrahub_sdk/pytest_plugin/utils.py b/infrahub_sdk/pytest_plugin/utils.py index 3923832b..249525ee 100644 --- a/infrahub_sdk/pytest_plugin/utils.py +++ b/infrahub_sdk/pytest_plugin/utils.py @@ -2,8 +2,7 @@ import yaml -from infrahub_sdk.schema import InfrahubRepositoryConfig - +from ..schema import InfrahubRepositoryConfig from .exceptions import FileNotValidError diff --git a/infrahub_sdk/query_groups.py b/infrahub_sdk/query_groups.py index 75002f80..eb980e6d 100644 --- a/infrahub_sdk/query_groups.py +++ b/infrahub_sdk/query_groups.py @@ -2,14 +2,14 @@ from typing import TYPE_CHECKING, Optional -from infrahub_sdk.constants import InfrahubClientMode -from infrahub_sdk.exceptions import NodeNotFoundError -from infrahub_sdk.utils import dict_hash +from .constants import InfrahubClientMode +from .exceptions import NodeNotFoundError +from .utils import dict_hash if TYPE_CHECKING: - from infrahub_sdk.client import InfrahubClient, InfrahubClientSync - from infrahub_sdk.node import InfrahubNode, InfrahubNodeSync, RelatedNodeBase - from infrahub_sdk.schema import MainSchemaTypes + from .client import InfrahubClient, InfrahubClientSync + from .node import InfrahubNode, InfrahubNodeSync, RelatedNodeBase + from .schema import MainSchemaTypes class InfrahubGroupContextBase: @@ -49,7 +49,7 @@ def _get_params_as_str(self) -> str: """Convert the params in dict format, into a string""" params_as_str: list[str] = [] for key, value in self.params.items(): - params_as_str.append(f"{key}: {str(value)}") + params_as_str.append(f"{key}: {value!s}") return ", ".join(params_as_str) def _generate_group_name(self, suffix: Optional[str] = None) -> str: diff --git a/infrahub_sdk/recorder.py b/infrahub_sdk/recorder.py index 218cfcac..bf2a715a 100644 --- a/infrahub_sdk/recorder.py +++ b/infrahub_sdk/recorder.py @@ -8,7 +8,7 @@ import ujson from pydantic_settings import BaseSettings, SettingsConfigDict -from infrahub_sdk.utils import generate_request_filename +from .utils import generate_request_filename class RecorderType(str, enum.Enum): diff --git a/infrahub_sdk/schema.py b/infrahub_sdk/schema.py index d7d4fc15..051d5f86 100644 --- a/infrahub_sdk/schema.py +++ b/infrahub_sdk/schema.py @@ -10,15 +10,15 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator from typing_extensions import TypeAlias -from infrahub_sdk._importer import import_module -from infrahub_sdk.exceptions import InvalidResponseError, ModuleImportError, SchemaNotFoundError, ValidationError -from infrahub_sdk.generator import InfrahubGenerator -from infrahub_sdk.graphql import Mutation -from infrahub_sdk.utils import duplicates +from ._importer import import_module +from .exceptions import InvalidResponseError, ModuleImportError, SchemaNotFoundError, ValidationError +from .generator import InfrahubGenerator +from .graphql import Mutation +from .utils import duplicates if TYPE_CHECKING: - from infrahub_sdk.client import InfrahubClient, InfrahubClientSync, SchemaType, SchemaTypeSync - from infrahub_sdk.node import InfrahubNode, InfrahubNodeSync + from .client import InfrahubClient, InfrahubClientSync, SchemaType, SchemaTypeSync + from .node import InfrahubNode, InfrahubNodeSync InfrahubNodeTypes = Union[InfrahubNode, InfrahubNodeSync] @@ -532,13 +532,14 @@ async def get( kind: Union[type[Union[SchemaType, SchemaTypeSync]], str], branch: Optional[str] = None, refresh: bool = False, + timeout: Optional[int] = None, ) -> MainSchemaTypes: branch = branch or self.client.default_branch kind_str = self._get_schema_name(schema=kind) if refresh: - self.cache[branch] = await self.fetch(branch=branch) + self.cache[branch] = await self.fetch(branch=branch, timeout=timeout) if branch in self.cache and kind_str in self.cache[branch]: return self.cache[branch][kind_str] @@ -546,7 +547,7 @@ async def get( # Fetching the latest schema from the server if we didn't fetch it earlier # because we coulnd't find the object on the local cache if not refresh: - self.cache[branch] = await self.fetch(branch=branch) + self.cache[branch] = await self.fetch(branch=branch, timeout=timeout) if branch in self.cache and kind_str in self.cache[branch]: return self.cache[branch][kind_str] @@ -715,11 +716,14 @@ async def add_dropdown_option( dropdown_optional_args=dropdown_optional_args, ) - async def fetch(self, branch: str, namespaces: Optional[list[str]] = None) -> MutableMapping[str, MainSchemaTypes]: + async def fetch( + self, branch: str, namespaces: Optional[list[str]] = None, timeout: Optional[int] = None + ) -> MutableMapping[str, MainSchemaTypes]: """Fetch the schema from the server for a given branch. Args: branch (str): Name of the branch to fetch the schema for. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. Returns: dict[str, MainSchemaTypes]: Dictionary of all schema organized by kind @@ -730,7 +734,7 @@ async def fetch(self, branch: str, namespaces: Optional[list[str]] = None) -> Mu query_params = urlencode(url_parts) url = f"{self.client.address}/api/schema?{query_params}" - response = await self.client._get(url=url) + response = await self.client._get(url=url, timeout=timeout) response.raise_for_status() data: MutableMapping[str, Any] = response.json() @@ -782,6 +786,7 @@ def get( kind: Union[type[Union[SchemaType, SchemaTypeSync]], str], branch: Optional[str] = None, refresh: bool = False, + timeout: Optional[int] = None, ) -> MainSchemaTypes: branch = branch or self.client.default_branch @@ -796,7 +801,7 @@ def get( # Fetching the latest schema from the server if we didn't fetch it earlier # because we coulnd't find the object on the local cache if not refresh: - self.cache[branch] = self.fetch(branch=branch) + self.cache[branch] = self.fetch(branch=branch, timeout=timeout) if branch in self.cache and kind_str in self.cache[branch]: return self.cache[branch][kind_str] @@ -915,11 +920,14 @@ def add_dropdown_option( dropdown_optional_args=dropdown_optional_args, ) - def fetch(self, branch: str, namespaces: Optional[list[str]] = None) -> MutableMapping[str, MainSchemaTypes]: + def fetch( + self, branch: str, namespaces: Optional[list[str]] = None, timeout: Optional[int] = None + ) -> MutableMapping[str, MainSchemaTypes]: """Fetch the schema from the server for a given branch. Args: branch (str): Name of the branch to fetch the schema for. + timeout (int, optional): Overrides default timeout used when querying the graphql API. Specified in seconds. Returns: dict[str, MainSchemaTypes]: Dictionary of all schema organized by kind @@ -930,7 +938,7 @@ def fetch(self, branch: str, namespaces: Optional[list[str]] = None) -> MutableM query_params = urlencode(url_parts) url = f"{self.client.address}/api/schema?{query_params}" - response = self.client._get(url=url) + response = self.client._get(url=url, timeout=timeout) response.raise_for_status() data: MutableMapping[str, Any] = response.json() @@ -983,6 +991,4 @@ class SchemaLoadResponse(BaseModel): @property def schema_updated(self) -> bool: - if self.hash and self.previous_hash and self.hash != self.previous_hash: - return True - return False + return bool(self.hash and self.previous_hash and self.hash != self.previous_hash) diff --git a/infrahub_sdk/spec/__init__.py b/infrahub_sdk/spec/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/infrahub_sdk/spec/menu.py b/infrahub_sdk/spec/menu.py new file mode 100644 index 00000000..407c53ca --- /dev/null +++ b/infrahub_sdk/spec/menu.py @@ -0,0 +1,34 @@ +from typing import Optional + +from ..yaml import InfrahubFile, InfrahubFileKind +from .object import InfrahubObjectFileData + + +class InfrahubMenuFileData(InfrahubObjectFileData): + kind: str = "CoreMenuItem" + + @classmethod + def enrich_node(cls, data: dict, context: dict) -> dict: + if "kind" in data and "path" not in data: + data["path"] = "/objects/" + data["kind"] + + if "list_index" in context and "order_weight" not in data: + data["order_weight"] = (context["list_index"] + 1) * 1000 + + return data + + +class MenuFile(InfrahubFile): + _spec: Optional[InfrahubMenuFileData] = None + + @property + def spec(self) -> InfrahubMenuFileData: + if not self._spec: + self._spec = InfrahubMenuFileData(**self.data.spec) + return self._spec + + def validate_content(self) -> None: + super().validate_content() + if self.kind != InfrahubFileKind.MENU: + raise ValueError("File is not an Infrahub Menu file") + self._spec = InfrahubMenuFileData(**self.data.spec) diff --git a/infrahub_sdk/spec/object.py b/infrahub_sdk/spec/object.py new file mode 100644 index 00000000..b9efb20d --- /dev/null +++ b/infrahub_sdk/spec/object.py @@ -0,0 +1,128 @@ +from typing import Any, Optional + +from pydantic import BaseModel, Field + +from ..client import InfrahubClient +from ..schema import MainSchemaTypes +from ..yaml import InfrahubFile, InfrahubFileKind + + +class InfrahubObjectFileData(BaseModel): + kind: str + data: list[dict[str, Any]] = Field(default_factory=list) + + @classmethod + def enrich_node(cls, data: dict, context: dict) -> dict: + return data + + @classmethod + async def create_node( + cls, + client: InfrahubClient, + schema: MainSchemaTypes, + data: dict, + context: Optional[dict] = None, + branch: Optional[str] = None, + default_schema_kind: Optional[str] = None, + ) -> None: + # First validate of all mandatory fields are present + for element in schema.mandatory_attribute_names + schema.mandatory_relationship_names: + if element not in data.keys(): + raise ValueError(f"{element} is mandatory") + + clean_data: dict[str, Any] = {} + + remaining_rels = [] + for key, value in data.items(): + if key in schema.attribute_names: + clean_data[key] = value + + if key in schema.relationship_names: + rel_schema = schema.get_relationship(name=key) + + if isinstance(value, dict) and "data" not in value: + raise ValueError(f"Relationship {key} must be a dict with 'data'") + + # This is a simple implementation for now, need to revisit once we have the integration tests + if isinstance(value, (list)): + clean_data[key] = value + elif rel_schema.cardinality == "one" and isinstance(value, str): + clean_data[key] = [value] + else: + remaining_rels.append(key) + + if context: + clean_context = { + ckey: cvalue + for ckey, cvalue in context.items() + if ckey in schema.relationship_names + schema.attribute_names + } + clean_data.update(clean_context) + + clean_data = cls.enrich_node(data=clean_data, context=context or {}) + + node = await client.create(kind=schema.kind, branch=branch, data=clean_data) + await node.save(allow_upsert=True) + display_label = node.get_human_friendly_id_as_string() or f"{node.get_kind()} : {node.id}" + client.log.info(f"Node: {display_label}") + + for rel in remaining_rels: + # identify what is the name of the relationship on the other side + if not isinstance(data[rel], dict) and "data" in data[rel]: + raise ValueError(f"relationship {rel} must be a dict with 'data'") + + rel_schema = schema.get_relationship(name=rel) + peer_kind = data[rel].get("kind", default_schema_kind) or rel_schema.peer + peer_schema = await client.schema.get(kind=peer_kind, branch=branch) + + if rel_schema.identifier is None: + raise ValueError("identifier must be defined") + + peer_rel = peer_schema.get_relationship_by_identifier(id=rel_schema.identifier) + + rel_data = data[rel]["data"] + context = {} + if peer_rel: + context[peer_rel.name] = node.id + + if rel_schema.cardinality == "one" and isinstance(rel_data, dict): + await cls.create_node( + client=client, + schema=peer_schema, + data=rel_data, + context=context, + branch=branch, + default_schema_kind=default_schema_kind, + ) + + elif rel_schema.cardinality == "many" and isinstance(rel_data, list): + for idx, peer_data in enumerate(rel_data): + context["list_index"] = idx + await cls.create_node( + client=client, + schema=peer_schema, + data=peer_data, + context=context, + branch=branch, + default_schema_kind=default_schema_kind, + ) + else: + raise ValueError( + f"Relationship {rel_schema.name} doesn't have the right format {rel_schema.cardinality} / {type(rel_data)}" + ) + + +class ObjectFile(InfrahubFile): + _spec: Optional[InfrahubObjectFileData] = None + + @property + def spec(self) -> InfrahubObjectFileData: + if not self._spec: + self._spec = InfrahubObjectFileData(**self.data.spec) + return self._spec + + def validate_content(self) -> None: + super().validate_content() + if self.kind != InfrahubFileKind.OBJECT: + raise ValueError("File is not an Infrahub Object file") + self._spec = InfrahubObjectFileData(**self.data.spec) diff --git a/infrahub_sdk/store.py b/infrahub_sdk/store.py index 2289ce48..aace0a69 100644 --- a/infrahub_sdk/store.py +++ b/infrahub_sdk/store.py @@ -3,11 +3,11 @@ from collections import defaultdict from typing import TYPE_CHECKING, Any, Literal, Optional, Union, overload -from infrahub_sdk.exceptions import NodeNotFoundError +from .exceptions import NodeNotFoundError if TYPE_CHECKING: - from infrahub_sdk.client import SchemaType - from infrahub_sdk.node import InfrahubNode, InfrahubNodeSync + from .client import SchemaType + from .node import InfrahubNode, InfrahubNodeSync def get_schema_name(schema: Optional[Union[str, type[SchemaType]]] = None) -> Optional[str]: diff --git a/infrahub_sdk/task_report.py b/infrahub_sdk/task_report.py index 47b83056..f2130895 100644 --- a/infrahub_sdk/task_report.py +++ b/infrahub_sdk/task_report.py @@ -4,12 +4,12 @@ from typing_extensions import Self -from infrahub_sdk.uuidt import generate_uuid +from .uuidt import generate_uuid if TYPE_CHECKING: from types import TracebackType - from infrahub_sdk.client import InfrahubClient + from .client import InfrahubClient class Log(TypedDict): diff --git a/infrahub_sdk/transfer/exporter/json.py b/infrahub_sdk/transfer/exporter/json.py index d35cf961..92963be1 100644 --- a/infrahub_sdk/transfer/exporter/json.py +++ b/infrahub_sdk/transfer/exporter/json.py @@ -6,16 +6,15 @@ from rich.console import Console from rich.progress import Progress -from infrahub_sdk.client import InfrahubClient -from infrahub_sdk.queries import QUERY_RELATIONSHIPS -from infrahub_sdk.schema import MainSchemaTypes, NodeSchema - +from ...client import InfrahubClient +from ...queries import QUERY_RELATIONSHIPS +from ...schema import MainSchemaTypes, NodeSchema from ..constants import ILLEGAL_NAMESPACES from ..exceptions import FileAlreadyExistsError, InvalidNamespaceError from .interface import ExporterInterface if TYPE_CHECKING: - from infrahub_sdk.node import InfrahubNode + from .node import InfrahubNode class LineDelimitedJSONExporter(ExporterInterface): @@ -55,7 +54,7 @@ def identify_many_to_many_relationships( # Record the relationship only if it's not known in one way or another if not forward and not backward: - many_relationship_identifiers[(node_schema.kind, relationship.peer)] = relationship.identifier + many_relationship_identifiers[node_schema.kind, relationship.peer] = relationship.identifier return many_relationship_identifiers diff --git a/infrahub_sdk/transfer/importer/json.py b/infrahub_sdk/transfer/importer/json.py index f6ceeeda..1da225fa 100644 --- a/infrahub_sdk/transfer/importer/json.py +++ b/infrahub_sdk/transfer/importer/json.py @@ -8,17 +8,16 @@ from rich.console import Console from rich.progress import Progress -from infrahub_sdk.batch import InfrahubBatch -from infrahub_sdk.client import InfrahubClient -from infrahub_sdk.exceptions import GraphQLError -from infrahub_sdk.node import InfrahubNode, RelatedNode, RelationshipManager -from infrahub_sdk.transfer.schema_sorter import InfrahubSchemaTopologicalSorter - +from ...batch import InfrahubBatch +from ...client import InfrahubClient +from ...exceptions import GraphQLError +from ...node import InfrahubNode, RelatedNode, RelationshipManager +from ...transfer.schema_sorter import InfrahubSchemaTopologicalSorter from ..exceptions import TransferFileNotFoundError from .interface import ImporterInterface if TYPE_CHECKING: - from infrahub_sdk.schema import NodeSchema, RelationshipSchema + from ...schema import NodeSchema, RelationshipSchema class LineDelimitedJSONImporter(ImporterInterface): @@ -164,7 +163,7 @@ async def execute_batches( self, batches: list[InfrahubBatch], progress_bar_message: str = "Executing batches" ) -> Sequence[Any]: if self.console: - task_count = sum((batch.num_tasks for batch in batches)) + task_count = sum(batch.num_tasks for batch in batches) progress = Progress() progress.start() progress_task = progress.add_task(f"{progress_bar_message}...", total=task_count) diff --git a/infrahub_sdk/transfer/schema_sorter.py b/infrahub_sdk/transfer/schema_sorter.py index 2ef87cca..fc8b0d4b 100644 --- a/infrahub_sdk/transfer/schema_sorter.py +++ b/infrahub_sdk/transfer/schema_sorter.py @@ -1,7 +1,6 @@ from typing import Optional, Sequence -from infrahub_sdk.schema import BaseNodeSchema - +from ..schema import BaseNodeSchema from ..topological_sort import DependencyCycleExistsError, topological_sort from .exceptions import SchemaImportError diff --git a/infrahub_sdk/transforms.py b/infrahub_sdk/transforms.py index bb277068..e9fc43c5 100644 --- a/infrahub_sdk/transforms.py +++ b/infrahub_sdk/transforms.py @@ -9,8 +9,7 @@ from git import Repo -from infrahub_sdk import InfrahubClient - +from . import InfrahubClient from .exceptions import InfrahubTransformNotFoundError if TYPE_CHECKING: @@ -58,7 +57,7 @@ def client(self) -> InfrahubClient: async def init(cls, client: Optional[InfrahubClient] = None, *args: Any, **kwargs: Any) -> InfrahubTransform: """Async init method, If an existing InfrahubClient client hasn't been provided, one will be created automatically.""" warnings.warn( - f"{cls.__class__.__name__}.init has been deprecated and will be removed in Infrahub SDK 0.15.0 or the next major version", + f"{cls.__class__.__name__}.init has been deprecated and will be removed in the version after Infrahub SDK 1.0.0", DeprecationWarning, stacklevel=1, ) diff --git a/infrahub_sdk/utils.py b/infrahub_sdk/utils.py index 0ae3e576..ae2e8800 100644 --- a/infrahub_sdk/utils.py +++ b/infrahub_sdk/utils.py @@ -16,7 +16,7 @@ SelectionSetNode, ) -from infrahub_sdk.exceptions import JsonDecodeError +from .exceptions import JsonDecodeError if TYPE_CHECKING: from graphql import GraphQLResolveInfo diff --git a/infrahub_sdk/uuidt.py b/infrahub_sdk/uuidt.py index d0f6418d..1aa39307 100644 --- a/infrahub_sdk/uuidt.py +++ b/infrahub_sdk/uuidt.py @@ -7,7 +7,7 @@ from typing import Optional from uuid import UUID -from infrahub_sdk.utils import base16encode +from .utils import base16encode BASE = 16 DIVISOR = BASE - 1 diff --git a/infrahub_sdk/yaml.py b/infrahub_sdk/yaml.py index aa6da1a1..92ebeed4 100644 --- a/infrahub_sdk/yaml.py +++ b/infrahub_sdk/yaml.py @@ -1,20 +1,49 @@ +from enum import Enum from pathlib import Path -from typing import Optional +from typing import Any, Optional import yaml -from pydantic import BaseModel +from pydantic import BaseModel, Field +from typing_extensions import Self +from .ctl._file import read_file +from .ctl.exceptions import FileNotValidError +from .utils import find_files -class SchemaFile(BaseModel): + +class InfrahubFileApiVersion(str, Enum): + V1 = "infrahub.app/v1" + + +class InfrahubFileKind(str, Enum): + MENU = "Menu" + OBJECT = "Object" + + +class InfrahubFileData(BaseModel): + api_version: InfrahubFileApiVersion = Field(InfrahubFileApiVersion.V1, alias="apiVersion") + kind: InfrahubFileKind + spec: dict + metadata: Optional[dict] = Field(default_factory=dict) + + +class LocalFile(BaseModel): identifier: Optional[str] = None location: Path content: Optional[dict] = None valid: bool = True error_message: Optional[str] = None + +class YamlFile(LocalFile): def load_content(self) -> None: try: - self.content = yaml.safe_load(self.location.read_text()) + self.content = yaml.safe_load(read_file(self.location)) + except FileNotValidError as exc: + self.error_message = exc.message + self.valid = False + return + except yaml.YAMLError: self.error_message = "Invalid YAML/JSON file" self.valid = False @@ -23,3 +52,54 @@ def load_content(self) -> None: if not self.content: self.error_message = "Empty YAML/JSON file" self.valid = False + + def validate_content(self) -> None: + pass + + @classmethod + def load_from_disk(cls, paths: list[Path]) -> list[Self]: + yaml_files: list[Self] = [] + for file_path in paths: + if file_path.is_file(): + yaml_file = cls(location=file_path) + yaml_file.load_content() + yaml_files.append(yaml_file) + elif file_path.is_dir(): + files = find_files(extension=["yaml", "yml", "json"], directory=file_path) + for item in files: + yaml_file = cls(location=item) + yaml_file.load_content() + yaml_files.append(yaml_file) + else: + raise FileNotValidError(name=str(file_path), message=f"{file_path} does not exist!") + + return yaml_files + + +class InfrahubFile(YamlFile): + _data: Optional[InfrahubFileData] = None + + @property + def data(self) -> InfrahubFileData: + if not self._data: + raise ValueError("_data hasn't been initialized yet") + return self._data + + @property + def version(self) -> InfrahubFileApiVersion: + return self.data.api_version + + @property + def kind(self) -> InfrahubFileKind: + return self.data.kind + + def validate_content(self) -> None: + if not self.content: + raise ValueError("Content hasn't been loaded yet") + self._data = InfrahubFileData(**self.content) + + +class SchemaFile(YamlFile): + @property + def payload(self) -> dict[str, Any]: + return self.content or {} diff --git a/poetry.lock b/poetry.lock index fdc0609a..6a639d59 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1645,29 +1645,29 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.5.0" +version = "0.7.1" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.5.0-py3-none-linux_armv6l.whl", hash = "sha256:ee770ea8ab38918f34e7560a597cc0a8c9a193aaa01bfbd879ef43cb06bd9c4c"}, - {file = "ruff-0.5.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:38f3b8327b3cb43474559d435f5fa65dacf723351c159ed0dc567f7ab735d1b6"}, - {file = "ruff-0.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7594f8df5404a5c5c8f64b8311169879f6cf42142da644c7e0ba3c3f14130370"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adc7012d6ec85032bc4e9065110df205752d64010bed5f958d25dbee9ce35de3"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d505fb93b0fabef974b168d9b27c3960714d2ecda24b6ffa6a87ac432905ea38"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dc5cfd3558f14513ed0d5b70ce531e28ea81a8a3b1b07f0f48421a3d9e7d80a"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:db3ca35265de239a1176d56a464b51557fce41095c37d6c406e658cf80bbb362"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b1a321c4f68809fddd9b282fab6a8d8db796b270fff44722589a8b946925a2a8"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c4dfcd8d34b143916994b3876b63d53f56724c03f8c1a33a253b7b1e6bf2a7d"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81e5facfc9f4a674c6a78c64d38becfbd5e4f739c31fcd9ce44c849f1fad9e4c"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e589e27971c2a3efff3fadafb16e5aef7ff93250f0134ec4b52052b673cf988d"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2ffbc3715a52b037bcb0f6ff524a9367f642cdc5817944f6af5479bbb2eb50e"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cd096e23c6a4f9c819525a437fa0a99d1c67a1b6bb30948d46f33afbc53596cf"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:46e193b36f2255729ad34a49c9a997d506e58f08555366b2108783b3064a0e1e"}, - {file = "ruff-0.5.0-py3-none-win32.whl", hash = "sha256:49141d267100f5ceff541b4e06552e98527870eafa1acc9dec9139c9ec5af64c"}, - {file = "ruff-0.5.0-py3-none-win_amd64.whl", hash = "sha256:e9118f60091047444c1b90952736ee7b1792910cab56e9b9a9ac20af94cd0440"}, - {file = "ruff-0.5.0-py3-none-win_arm64.whl", hash = "sha256:ed5c4df5c1fb4518abcb57725b576659542bdbe93366f4f329e8f398c4b71178"}, - {file = "ruff-0.5.0.tar.gz", hash = "sha256:eb641b5873492cf9bd45bc9c5ae5320648218e04386a5f0c264ad6ccce8226a1"}, + {file = "ruff-0.7.1-py3-none-linux_armv6l.whl", hash = "sha256:cb1bc5ed9403daa7da05475d615739cc0212e861b7306f314379d958592aaa89"}, + {file = "ruff-0.7.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:27c1c52a8d199a257ff1e5582d078eab7145129aa02721815ca8fa4f9612dc35"}, + {file = "ruff-0.7.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:588a34e1ef2ea55b4ddfec26bbe76bc866e92523d8c6cdec5e8aceefeff02d99"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94fc32f9cdf72dc75c451e5f072758b118ab8100727168a3df58502b43a599ca"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:985818742b833bffa543a84d1cc11b5e6871de1b4e0ac3060a59a2bae3969250"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32f1e8a192e261366c702c5fb2ece9f68d26625f198a25c408861c16dc2dea9c"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:699085bf05819588551b11751eff33e9ca58b1b86a6843e1b082a7de40da1565"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:344cc2b0814047dc8c3a8ff2cd1f3d808bb23c6658db830d25147339d9bf9ea7"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4316bbf69d5a859cc937890c7ac7a6551252b6a01b1d2c97e8fc96e45a7c8b4a"}, + {file = "ruff-0.7.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79d3af9dca4c56043e738a4d6dd1e9444b6d6c10598ac52d146e331eb155a8ad"}, + {file = "ruff-0.7.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c5c121b46abde94a505175524e51891f829414e093cd8326d6e741ecfc0a9112"}, + {file = "ruff-0.7.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8422104078324ea250886954e48f1373a8fe7de59283d747c3a7eca050b4e378"}, + {file = "ruff-0.7.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:56aad830af8a9db644e80098fe4984a948e2b6fc2e73891538f43bbe478461b8"}, + {file = "ruff-0.7.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:658304f02f68d3a83c998ad8bf91f9b4f53e93e5412b8f2388359d55869727fd"}, + {file = "ruff-0.7.1-py3-none-win32.whl", hash = "sha256:b517a2011333eb7ce2d402652ecaa0ac1a30c114fbbd55c6b8ee466a7f600ee9"}, + {file = "ruff-0.7.1-py3-none-win_amd64.whl", hash = "sha256:f38c41fcde1728736b4eb2b18850f6d1e3eedd9678c914dede554a70d5241307"}, + {file = "ruff-0.7.1-py3-none-win_arm64.whl", hash = "sha256:19aa200ec824c0f36d0c9114c8ec0087082021732979a359d6f3c390a6ff2a37"}, + {file = "ruff-0.7.1.tar.gz", hash = "sha256:9d8a41d4aa2dad1575adb98a82870cf5db5f76b2938cf2206c22c940034a36f4"}, ] [[package]] @@ -2065,4 +2065,4 @@ tests = ["Jinja2", "pytest", "pyyaml", "rich"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "da1358d88082ae278014e41b9a65c96aa9db5d3c7cbfdcf734da48679f87d9e3" +content-hash = "780e999965fa84c44b146fa9b5fe656b1c7919142dbf9e05b3996862ce6e256c" diff --git a/pyproject.toml b/pyproject.toml index 3556d56e..46aad3ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "infrahub-sdk" -version = "0.14.1" +version = "1.0.0" description = "Python Client to interact with Infrahub" authors = ["OpsMill "] readme = "README.md" @@ -60,7 +60,7 @@ pre-commit = "^2.20.0" types-toml = "*" types-ujson = "*" types-pyyaml = "*" -ruff = "0.5.0" +ruff = "0.7.1" pytest-xdist = "^3.3.1" types-python-slugify = "^8.0.0.3" invoke = "^2.2.0" @@ -155,30 +155,14 @@ disallow_untyped_defs = true module = "infrahub_sdk.ctl.check" ignore_errors = true -[[tool.mypy.overrides]] -module = "infrahub_sdk.ctl.cli_commands" -ignore_errors = true - -[[tool.mypy.overrides]] -module = "infrahub_sdk.ctl.exporter" -ignore_errors = true - [[tool.mypy.overrides]] module = "infrahub_sdk.ctl.generator" ignore_errors = true -[[tool.mypy.overrides]] -module = "infrahub_sdk.ctl.importer" -ignore_errors = true - [[tool.mypy.overrides]] module = "infrahub_sdk.ctl.schema" ignore_errors = true -[[tool.mypy.overrides]] -module = "infrahub_sdk.ctl.utils" -ignore_errors = true - [[tool.mypy.overrides]] module = "infrahub_sdk.utils" ignore_errors = true @@ -242,12 +226,9 @@ ignore = [ # like this so that we can reactivate them one by one. Alternatively ignored after further # # investigation if they are deemed to not make sense. # ################################################################################################## - "B007", # Loop control variable `result` not used within loop body "B008", # Do not perform function call `typer.Option` in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable "B904", # Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling - "B018", # Found useless attribute access. Either assign it to a variable or remove it. "C408", # Unnecessary `dict` call (rewrite as a literal) - "C414", # Unnecessary `list` call within `sorted()` "FURB110", # Replace ternary `if` expression with `or` operator "FURB113", # Use `lines.extend((" " * self.indentation + "}", "}"))` instead of repeatedly calling `lines.append()` "FURB177", # Prefer `Path.cwd()` over `Path().resolve()` for current-directory lookups @@ -268,24 +249,22 @@ ignore = [ "PTH100", # `os.path.abspath()` should be replaced by `Path.resolve()` "PTH109", # `os.getcwd()` should be replaced by `Path.cwd()` "RET504", # Unnecessary assignment to `data` before `return` statement - "RUF", # Unused `noqa` directive - "S105", # Possible hardcoded password assigned to: "PASS" + "RUF005", # Consider `[*path, str(key)]` instead of concatenation + "RUF015", # Prefer `next(iter(input_data["variables"].keys()))` over single element slice + "RUF029", # Function is declared `async`, but doesn't `await` or use `async` features. "S108", # Probable insecure usage of temporary file or directory "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes "S701", # By default, jinja2 sets `autoescape` to `False`. Consider using `autoescape=True` "SIM102", # Use a single `if` statement instead of nested `if` statements - "SIM103", # Return the condition directly "SIM105", # Use `contextlib.suppress(KeyError)` instead of `try`-`except`-`pass` "SIM108", # Use ternary operator `key_str = f"{value[ALIAS_KEY]}: {key}" if ALIAS_KEY in value and value[ALIAS_KEY] else key` instead of `if`-`else`-block "SIM110", # Use `return any(getattr(item, resource_field) == resource_id for item in getattr(self, RESOURCE_MAP[resource_type]))` instead of `for` loop "SIM114", # Combine `if` branches using logical `or` operator "SIM117", # Use a single `with` statement with multiple contexts instead of nested `with` statements "SIM118", # Use `key in dict` instead of `key in dict.keys) - "SIM300", # Yoda condition detected "SIM910", # Use `data.get(key)` instead of `data.get(key, None)` "UP007", # Use X | Y for type annotations "UP031", # Use format specifiers instead of percent format - "UP034", # Avoid extraneous parentheses ] @@ -312,7 +291,6 @@ max-complexity = 17 ################################################################################################## # Review and change the below later # ################################################################################################## - "ANN001", # Missing type annotation for function argument "ANN201", # ANN201 Missing return type annotation for public function "ANN202", # Missing return type annotation for private function "ANN204", # Missing return type annotation for special method @@ -326,10 +304,15 @@ max-complexity = 17 "PLR0904", # Too many public methods ] +"infrahub_sdk/pytest_plugin/models.py" = [ + "S105", # 'PASS' is not a password but a state +] + + "tests/**/*.py" = [ "PLR2004", # Magic value used in comparison "S101", # Use of assert detected - "S106", # Possible hardcoded password assigned to variable + "S105", # Possible hardcoded password assigned to variable "S106", # Possible hardcoded password assigned to argument ################################################################################################## diff --git a/tests/fixtures/schema_01.json b/tests/fixtures/schema_01.json index 460afadd..bf6f016e 100644 --- a/tests/fixtures/schema_01.json +++ b/tests/fixtures/schema_01.json @@ -49,52 +49,13 @@ "inherited": false, "cardinality": "many", "branch": "aware", - "optional": true, - "filters": [ - { - "name": "id", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - } - ] + "optional": true } ], "label": null, "inherit_from": [], "branch": "aware", - "default_filter": "name__value", - "filters": [ - { - "name": "ids", - "kind": "List", - "description": null - }, - { - "name": "query__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - } - ] + "default_filter": "name__value" }, { "name": "Repository", @@ -200,24 +161,7 @@ "inherited": false, "cardinality": "many", "branch": "aware", - "optional": true, - "filters": [ - { - "name": "id", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - } - ] + "optional": true }, { "name": "queries", @@ -228,29 +172,7 @@ "inherited": false, "cardinality": "many", "branch": "aware", - "optional": true, - "filters": [ - { - "name": "id", - "kind": "String", - "description": null - }, - { - "name": "query__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - } - ] + "optional": true } ], "label": null, @@ -260,58 +182,8 @@ ], "branch": "aware", "default_filter": "name__value", - "human_friendly_id": ["name__value"], - "filters": [ - { - "name": "ids", - "kind": "List", - "description": null - }, - { - "name": "hfid", - "kind": "List", - "description": null - }, - { - "name": "username__value", - "kind": "String", - "description": null - }, - { - "name": "type__value", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - }, - { - "name": "commit__value", - "kind": "String", - "description": null - }, - { - "name": "location__value", - "kind": "String", - "description": null - }, - { - "name": "password__value", - "kind": "String", - "description": null - }, - { - "name": "default_branch__value", - "kind": "String", - "description": null - } + "human_friendly_id": [ + "name__value" ] }, { @@ -341,64 +213,70 @@ "branch": "aware", "optional": true }, - { - "name": "status", - "kind": "Dropdown", + { + "name": "status", + "kind": "Dropdown", "branch": "aware", - "optional": true, - "choices": [ - { - "name": "active", - "label": "Active", - "description": "A status", - "color": "#ffffff" - } - ] - }, - { - "name": "mode", - "kind": "Text", + "optional": true, + "choices": [ + { + "name": "active", + "label": "Active", + "description": "A status", + "color": "#ffffff" + } + ] + }, + { + "name": "mode", + "kind": "Text", "branch": "aware", - "optional": true, - "enum": ["easy"] - } + "optional": true, + "enum": [ + "easy" + ] + } ], "relationships": [], "label": null, "inherit_from": [], "branch": "aware", + "default_filter": "name__value" + }, + { + "name": "Location", + "namespace": "Builtin", "default_filter": "name__value", - "filters": [ + "attributes": [ { - "name": "ids", - "kind": "List", - "description": null + "name": "name", + "kind": "String", + "unique": true }, { - "name": "name__value", + "name": "description", "kind": "String", - "description": null + "optional": true }, { - "name": "description__value", - "kind": "String", - "description": null + "name": "type", + "kind": "String" } - ] - }, - { - "name": "Location", - "namespace": "Builtin", - "default_filter": "name__value", - "attributes": [ - {"name": "name", "kind": "String", "unique": true}, - {"name": "description", "kind": "String", "optional": true}, - {"name": "type", "kind": "String"} ], "relationships": [ - {"name": "tags", "peer": "BuiltinTag", "optional": true, "cardinality": "many"}, - {"name": "primary_tag", "peer": "BuiltinTag", "optional": true, "cardinality": "one"} + { + "name": "tags", + "peer": "BuiltinTag", + "optional": true, + "cardinality": "many" + }, + { + "name": "primary_tag", + "peer": "BuiltinTag", + "optional": true, + "cardinality": "one" + } ] } ] -} +} \ No newline at end of file diff --git a/tests/fixtures/schema_02.json b/tests/fixtures/schema_02.json index 52553760..1417053f 100644 --- a/tests/fixtures/schema_02.json +++ b/tests/fixtures/schema_02.json @@ -11,7 +11,10 @@ "attributes": [], "relationships": [], "label": "Node", - "used_by": ["BuiltinTag", "BuiltinLocation"], + "used_by": [ + "BuiltinTag", + "BuiltinLocation" + ], "kind": "CoreNode" }, { @@ -20,8 +23,12 @@ "description": "A Git Repository integrated with Infrahub", "default_filter": "name__value", "branch": "agnostic", - "order_by": ["name__value"], - "display_labels": ["name__value"], + "order_by": [ + "name__value" + ], + "display_labels": [ + "name__value" + ], "attributes": [ { "name": "name", @@ -219,8 +226,12 @@ "description": "A Git Repository integrated with Infrahub", "default_filter": "name__value", "branch": "aware", - "order_by": ["name__value"], - "display_labels": ["name__value"], + "order_by": [ + "name__value" + ], + "display_labels": [ + "name__value" + ], "attributes": [ { "name": "default_branch", @@ -422,7 +433,9 @@ } ], "label": "Repository", - "inherit_from": ["CoreGenericRepository"], + "inherit_from": [ + "CoreGenericRepository" + ], "kind": "CoreRepository" }, { @@ -432,8 +445,12 @@ "description": "A Git Repository integrated with Infrahub, Git-side will not be updated", "default_filter": "name__value", "branch": "aware", - "order_by": ["name__value"], - "display_labels": ["name__value"], + "order_by": [ + "name__value" + ], + "display_labels": [ + "name__value" + ], "attributes": [ { "id": "17a73306-2d08-182e-43e6-1677aaae0c06", @@ -708,52 +725,13 @@ "inherited": false, "cardinality": "many", "branch": "aware", - "optional": true, - "filters": [ - { - "name": "id", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - } - ] + "optional": true } ], "label": null, "inherit_from": [], "branch": "aware", - "default_filter": "name__value", - "filters": [ - { - "name": "ids", - "kind": "List", - "description": null - }, - { - "name": "query__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - } - ] + "default_filter": "name__value" }, { "name": "Repository", @@ -877,24 +855,7 @@ "inherited": false, "cardinality": "many", "branch": "aware", - "optional": true, - "filters": [ - { - "name": "id", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - } - ] + "optional": true }, { "name": "queries", @@ -905,29 +866,7 @@ "inherited": false, "cardinality": "many", "branch": "aware", - "optional": true, - "filters": [ - { - "name": "id", - "kind": "String", - "description": null - }, - { - "name": "query__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - } - ] + "optional": true } ], "label": null, @@ -936,54 +875,7 @@ "DataSource" ], "branch": "aware", - "default_filter": "name__value", - "filters": [ - { - "name": "ids", - "kind": "List", - "description": null - }, - { - "name": "username__value", - "kind": "String", - "description": null - }, - { - "name": "type__value", - "kind": "String", - "description": null - }, - { - "name": "name__value", - "kind": "String", - "description": null - }, - { - "name": "description__value", - "kind": "String", - "description": null - }, - { - "name": "commit__value", - "kind": "String", - "description": null - }, - { - "name": "location__value", - "kind": "String", - "description": null - }, - { - "name": "password__value", - "kind": "String", - "description": null - }, - { - "name": "default_branch__value", - "kind": "String", - "description": null - } - ] + "default_filter": "name__value" }, { "name": "Tag", @@ -1015,40 +907,48 @@ ], "relationships": [], "label": null, - "inherit_from": ["CoreNode"], + "inherit_from": [ + "CoreNode" + ], "branch": "aware", + "default_filter": "name__value" + }, + { + "name": "Location", + "namespace": "Builtin", "default_filter": "name__value", - "filters": [ + "inherit_from": [ + "CoreNode" + ], + "attributes": [ { - "name": "ids", - "kind": "List", - "description": null + "name": "name", + "kind": "String", + "unique": true }, { - "name": "name__value", + "name": "description", "kind": "String", - "description": null + "optional": true }, { - "name": "description__value", - "kind": "String", - "description": null + "name": "type", + "kind": "String" } - ] - }, - { - "name": "Location", - "namespace": "Builtin", - "default_filter": "name__value", - "inherit_from": ["CoreNode"], - "attributes": [ - {"name": "name", "kind": "String", "unique": true}, - {"name": "description", "kind": "String", "optional": true}, - {"name": "type", "kind": "String"} ], "relationships": [ - {"name": "tags", "peer": "BuiltinTag", "optional": true, "cardinality": "many"}, - {"name": "primary_tag", "peer": "BuiltinTag", "optional": true, "cardinality": "one"} + { + "name": "tags", + "peer": "BuiltinTag", + "optional": true, + "cardinality": "many" + }, + { + "name": "primary_tag", + "peer": "BuiltinTag", + "optional": true, + "cardinality": "one" + } ] } ] diff --git a/tests/fixtures/schema_03.json b/tests/fixtures/schema_03.json index 924dd420..2c77477e 100644 --- a/tests/fixtures/schema_03.json +++ b/tests/fixtures/schema_03.json @@ -1,974 +1,201 @@ { - "nodes": [ - { - "id": "1799f63a-56b4-7f6c-304e-c510849dcb58", - "name": "Artifact", - "namespace": "Core", - "description": null, - "default_filter": "name__value", - "branch": "local", - "order_by": [ - "name__value" - ], - "display_labels": [ - "name__value" - ], - "attributes": [ - { - "id": "1799f63a-5709-60c0-3049-c517825cf4c9", - "name": "name", - "kind": "Text", - "namespace": "Attribute", - "label": "Name", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "local", - "optional": false, - "order_weight": 1000 - }, - { - "id": "1799f63a-5766-dcb8-304d-c51e643fd5aa", - "name": "status", - "kind": "Text", - "namespace": "Attribute", - "label": "Status", - "description": null, - "default_value": null, - "enum": [ - "Error", - "Pending", - "Processing", - "Ready" - ], - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "local", - "optional": false, - "order_weight": 2000 - }, - { - "id": "1799f63a-57c7-bcd9-3041-c51b45223d54", - "name": "content_type", - "kind": "Text", - "namespace": "Attribute", - "label": "Content Type", - "description": null, - "default_value": null, - "enum": [ - "application/json", - "text/plain" - ], - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "local", - "optional": false, - "order_weight": 3000 - }, - { - "id": "1799f63a-582f-ec8f-304c-c51ff4f83720", - "name": "checksum", - "kind": "Text", - "namespace": "Attribute", - "label": "Checksum", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "local", - "optional": true, - "order_weight": 4000 - }, - { - "id": "1799f63a-5898-86b8-304e-c5143fc3cb31", - "name": "storage_id", - "kind": "Text", - "namespace": "Attribute", - "label": "Storage Id", - "description": "ID of the file in the object store", - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "local", - "optional": true, - "order_weight": 5000 - }, - { - "id": "1799f63a-5900-ba56-304e-c515eef9ed77", - "name": "parameters", - "kind": "JSON", - "namespace": "Attribute", - "label": "Parameters", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "local", - "optional": true, - "order_weight": 6000 - } - ], - "relationships": [ - { - "id": "1799f63a-595e-7d97-304d-c51df7daa9a4", - "name": "object", - "peer": "CoreNode", - "kind": "Attribute", - "label": "Object", - "description": null, - "identifier": "artifact__node", - "inherited": false, - "cardinality": "one", - "branch": "local", - "optional": false, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 7000 - }, - { - "id": "1799f63a-59b1-183d-3041-c5191c3136f6", - "name": "definition", - "peer": "CoreArtifactDefinition", - "kind": "Attribute", - "label": "Definition", - "description": null, - "identifier": "artifact__artifact_definition", - "inherited": false, - "cardinality": "one", - "branch": "local", - "optional": false, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 8000 - }, - { - "id": "1799f63a-5a06-60c2-304b-c513a9abcdd8", - "name": "member_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Member Of Groups", - "description": null, - "identifier": "group_member", - "inherited": false, - "cardinality": "many", - "branch": "aware", - "optional": true, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 9000 - }, - { - "id": "1799f63a-5a59-c417-3044-c51c9c8e5131", - "name": "subscriber_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Subscriber Of Groups", - "description": null, - "identifier": "group_subscriber", - "inherited": false, - "cardinality": "many", - "branch": "aware", - "optional": true, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 10000 - } - ], - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__value", - "kind": "Text", - "enum": [ - "Error", - "Pending", - "Processing", - "Ready" - ], - "object_kind": null, - "description": null - }, - { - "name": "status__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "object__ids", - "kind": "Text", - "enum": null, - "object_kind": "CoreNode", - "description": null - }, - { - "name": "definition__ids", - "kind": "Text", - "enum": null, - "object_kind": "CoreArtifactDefinition", - "description": null - }, - { - "name": "definition__name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null + "nodes": [ + { + "id": "1799f63a-56b4-7f6c-304e-c510849dcb58", + "name": "Artifact", + "namespace": "Core", + "description": null, + "default_filter": "name__value", + "branch": "local", + "order_by": [ + "name__value" + ], + "display_labels": [ + "name__value" + ], + "attributes": [ + { + "id": "1799f63a-5709-60c0-3049-c517825cf4c9", + "name": "name", + "kind": "Text", + "namespace": "Attribute", + "label": "Name", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "local", + "optional": false, + "order_weight": 1000 + }, + { + "id": "1799f63a-5766-dcb8-304d-c51e643fd5aa", + "name": "status", + "kind": "Text", + "namespace": "Attribute", + "label": "Status", + "description": null, + "default_value": null, + "enum": [ + "Error", + "Pending", + "Processing", + "Ready" + ], + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "local", + "optional": false, + "order_weight": 2000 + }, + { + "id": "1799f63a-57c7-bcd9-3041-c51b45223d54", + "name": "content_type", + "kind": "Text", + "namespace": "Attribute", + "label": "Content Type", + "description": null, + "default_value": null, + "enum": [ + "application/json", + "text/plain" + ], + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "local", + "optional": false, + "order_weight": 3000 + }, + { + "id": "1799f63a-582f-ec8f-304c-c51ff4f83720", + "name": "checksum", + "kind": "Text", + "namespace": "Attribute", + "label": "Checksum", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "local", + "optional": true, + "order_weight": 4000 + }, + { + "id": "1799f63a-5898-86b8-304e-c5143fc3cb31", + "name": "storage_id", + "kind": "Text", + "namespace": "Attribute", + "label": "Storage Id", + "description": "ID of the file in the object store", + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "local", + "optional": true, + "order_weight": 5000 + }, + { + "id": "1799f63a-5900-ba56-304e-c515eef9ed77", + "name": "parameters", + "kind": "JSON", + "namespace": "Attribute", + "label": "Parameters", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "local", + "optional": true, + "order_weight": 6000 + } + ], + "relationships": [ + { + "id": "1799f63a-595e-7d97-304d-c51df7daa9a4", + "name": "object", + "peer": "CoreNode", + "kind": "Attribute", + "label": "Object", + "description": null, + "identifier": "artifact__node", + "inherited": false, + "cardinality": "one", + "branch": "local", + "optional": false, + "order_weight": 7000 + }, + { + "id": "1799f63a-59b1-183d-3041-c5191c3136f6", + "name": "definition", + "peer": "CoreArtifactDefinition", + "kind": "Attribute", + "label": "Definition", + "description": null, + "identifier": "artifact__artifact_definition", + "inherited": false, + "cardinality": "one", + "branch": "local", + "optional": false, + "order_weight": 8000 + }, + { + "id": "1799f63a-5a06-60c2-304b-c513a9abcdd8", + "name": "member_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Member Of Groups", + "description": null, + "identifier": "group_member", + "inherited": false, + "cardinality": "many", + "branch": "aware", + "optional": true, + "order_weight": 9000 + }, + { + "id": "1799f63a-5a59-c417-3044-c51c9c8e5131", + "name": "subscriber_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Subscriber Of Groups", + "description": null, + "identifier": "group_subscriber", + "inherited": false, + "cardinality": "many", + "branch": "aware", + "optional": true, + "order_weight": 10000 + } + ], + "include_in_menu": false, + "menu_placement": null, + "icon": null, + "label": "Artifact", + "inherit_from": [], + "kind": "CoreArtifact" } - ], - "include_in_menu": false, - "menu_placement": null, - "icon": null, - "label": "Artifact", - "inherit_from": [], - "kind": "CoreArtifact" - } - ], - "generics": [] -} + ], + "generics": [] +} \ No newline at end of file diff --git a/tests/fixtures/schema_04.json b/tests/fixtures/schema_04.json index 92b6d58f..89c5f3d1 100644 --- a/tests/fixtures/schema_04.json +++ b/tests/fixtures/schema_04.json @@ -1,2097 +1,387 @@ { - "nodes": [ - { - "id": "179be3f5-eab5-9d05-301d-c51f20da7fbd", - "name": "Artifact", - "namespace": "Core", - "description": null, - "default_filter": "name__value", - "branch": "local", - "order_by": [ - "name__value" - ], - "display_labels": [ - "name__value" - ], - "attributes": [ - { - "id": "179be3f5-eb1c-bd16-301a-c511fdc69f85", - "name": "name", - "kind": "Text", - "namespace": "Attribute", - "label": "Name", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "read_only": false, - "inherited": false, - "unique": false, - "branch": "local", - "optional": false, - "order_weight": 1000, - "choices": null - }, - { - "id": "179be3f5-eb8d-c1dd-3017-c514f5cc3594", - "name": "status", - "kind": "Text", - "namespace": "Attribute", - "label": "Status", - "description": null, - "default_value": null, - "enum": [ - "Error", - "Pending", - "Processing", - "Ready" - ], - "regex": null, - "max_length": null, - "min_length": null, - "read_only": false, - "inherited": false, - "unique": false, - "branch": "local", - "optional": false, - "order_weight": 2000, - "choices": null - }, - { - "id": "179be3f5-ec02-7296-3016-c510fbc0122f", - "name": "content_type", - "kind": "Text", - "namespace": "Attribute", - "label": "Content Type", - "description": null, - "default_value": null, - "enum": [ - "application/json", - "text/plain" - ], - "regex": null, - "max_length": null, - "min_length": null, - "read_only": false, - "inherited": false, - "unique": false, - "branch": "local", - "optional": false, - "order_weight": 3000, - "choices": null - }, - { - "id": "179be3f5-ec73-ae37-301d-c51b20302e14", - "name": "checksum", - "kind": "Text", - "namespace": "Attribute", - "label": "Checksum", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "read_only": false, - "inherited": false, - "unique": false, - "branch": "local", - "optional": true, - "order_weight": 4000, - "choices": null - }, - { - "id": "179be3f5-ece7-c18c-3011-c51a0e3e273e", - "name": "storage_id", - "kind": "Text", - "namespace": "Attribute", - "label": "Storage Id", - "description": "ID of the file in the object store", - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "read_only": false, - "inherited": false, - "unique": false, - "branch": "local", - "optional": true, - "order_weight": 5000, - "choices": null - }, - { - "id": "179be3f5-ed5e-53b7-3011-c5143efc850e", - "name": "parameters", - "kind": "JSON", - "namespace": "Attribute", - "label": "Parameters", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "read_only": false, - "inherited": false, - "unique": false, - "branch": "local", - "optional": true, - "order_weight": 6000, - "choices": null - } - ], - "relationships": [ - { - "id": "179be3f5-edcd-7f06-3011-c51a4a621a7e", - "name": "object", - "peer": "CoreNode", - "kind": "Attribute", - "label": "Object", - "description": null, - "identifier": "artifact__node", - "inherited": false, - "cardinality": "one", - "branch": "local", - "optional": false, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 7000 - }, - { - "id": "179be3f5-ee2d-1349-3013-c517a643565b", - "name": "definition", - "peer": "CoreArtifactDefinition", - "kind": "Attribute", - "label": "Definition", - "description": null, - "identifier": "artifact__artifact_definition", - "inherited": false, - "cardinality": "one", - "branch": "local", - "optional": false, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 8000 - }, - { - "id": "179be3f5-ee86-fd31-301c-c51594ed3876", - "name": "member_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Member Of Groups", - "description": null, - "identifier": "group_member", - "inherited": false, - "cardinality": "many", - "branch": "aware", - "optional": true, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 9000 - }, - { - "id": "179be3f5-eee9-ca52-301d-c5166012d5ce", - "name": "subscriber_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Subscriber Of Groups", - "description": null, - "identifier": "group_subscriber", - "inherited": false, - "cardinality": "many", - "branch": "aware", - "optional": true, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 10000 - } - ], - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__value", - "kind": "Text", - "enum": [ - "Error", - "Pending", - "Processing", - "Ready" - ], - "object_kind": null, - "description": null - }, - { - "name": "status__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "status__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "checksum__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "storage_id__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "object__ids", - "kind": "Text", - "enum": null, - "object_kind": "CoreNode", - "description": null - }, - { - "name": "definition__ids", - "kind": "Text", - "enum": null, - "object_kind": "CoreArtifactDefinition", - "description": null - }, - { - "name": "definition__name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__artifact_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "definition__content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "include_in_menu": false, - "menu_placement": null, - "icon": null, - "label": "Artifact", - "inherit_from": [], - "kind": "CoreArtifact", - "hash": "eecebc6d23a92ea79a54f8676352ebb5" - }, - { - "id": "1799f63a-5b6b-cb21-304a-c51964ff356c", - "name": "ArtifactDefinition", - "namespace": "Core", - "description": null, - "default_filter": "name__value", - "branch": "aware", - "order_by": [ - "name__value" - ], - "display_labels": [ - "name__value" - ], - "attributes": [ - { - "id": "1799f63a-5bc6-0329-304f-c5133b0a3e09", - "name": "name", - "kind": "Text", - "namespace": "Attribute", - "label": "Name", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": true, - "branch": "aware", - "optional": false, - "order_weight": 1000 - }, - { - "id": "1799f63a-5c26-749d-304a-c5130edc5d10", - "name": "artifact_name", - "kind": "Text", - "namespace": "Attribute", - "label": "Artifact Name", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "aware", - "optional": false, - "order_weight": 2000 - }, - { - "id": "1799f63a-5c85-969e-3048-c5102fe0d7d0", - "name": "description", - "kind": "Text", - "namespace": "Attribute", - "label": "Description", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "aware", - "optional": true, - "order_weight": 3000 - }, - { - "id": "1799f63a-5ce2-84fb-304a-c51541e59ee2", - "name": "parameters", - "kind": "JSON", - "namespace": "Attribute", - "label": "Parameters", - "description": null, - "default_value": null, - "enum": null, - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "aware", - "optional": false, - "order_weight": 4000 - }, - { - "id": "1799f63a-5d69-d3fa-3049-c51efd44dcbf", - "name": "content_type", - "kind": "Text", - "namespace": "Attribute", - "label": "Content Type", - "description": null, - "default_value": null, - "enum": [ - "application/json", - "text/plain" - ], - "regex": null, - "max_length": null, - "min_length": null, - "inherited": false, - "unique": false, - "branch": "aware", - "optional": false, - "order_weight": 5000 - } - ], - "relationships": [ - { - "id": "1799f63a-5dd2-3fc0-3046-c51b909b6a36", - "name": "targets", - "peer": "CoreGroup", - "kind": "Attribute", - "label": "Targets", - "description": null, - "identifier": "artifact_definition___group", - "inherited": false, - "cardinality": "one", - "branch": "aware", - "optional": false, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 6000 - }, - { - "id": "1799f63a-5e27-e84c-3046-c514bd181b05", - "name": "transformation", - "peer": "CoreTransformation", - "kind": "Attribute", - "label": "Transformation", - "description": null, - "identifier": "artifact_definition___transformation", - "inherited": false, - "cardinality": "one", - "branch": "aware", - "optional": false, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "timeout__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "timeout__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "timeout__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "timeout__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "timeout__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 7000 - }, - { - "id": "1799f63a-5e7d-5a28-3048-c51eb5055587", - "name": "member_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Member Of Groups", - "description": null, - "identifier": "group_member", - "inherited": false, - "cardinality": "many", - "branch": "aware", - "optional": true, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 8000 - }, - { - "id": "1799f63a-5ed0-c577-3048-c512f9ff312a", - "name": "subscriber_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Subscriber Of Groups", - "description": null, - "identifier": "group_subscriber", - "inherited": false, - "cardinality": "many", - "branch": "aware", - "optional": true, - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "order_weight": 9000 - } - ], - "filters": [ - { - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "artifact_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__value", - "kind": "Text", - "enum": [ - "application/json", - "text/plain" - ], - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "content_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "any__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__ids", - "kind": "Text", - "enum": null, - "object_kind": "CoreGroup", - "description": null - }, - { - "name": "targets__name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "targets__description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__ids", - "kind": "Text", - "enum": null, - "object_kind": "CoreTransformation", - "description": null - }, - { - "name": "transformation__name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__timeout__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__timeout__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__timeout__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__timeout__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "name": "transformation__timeout__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null + "nodes": [ + { + "id": "179be3f5-eab5-9d05-301d-c51f20da7fbd", + "name": "Artifact", + "namespace": "Core", + "description": null, + "default_filter": "name__value", + "branch": "local", + "order_by": [ + "name__value" + ], + "display_labels": [ + "name__value" + ], + "attributes": [ + { + "id": "179be3f5-eb1c-bd16-301a-c511fdc69f85", + "name": "name", + "kind": "Text", + "namespace": "Attribute", + "label": "Name", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "read_only": false, + "inherited": false, + "unique": false, + "branch": "local", + "optional": false, + "order_weight": 1000, + "choices": null + }, + { + "id": "179be3f5-eb8d-c1dd-3017-c514f5cc3594", + "name": "status", + "kind": "Text", + "namespace": "Attribute", + "label": "Status", + "description": null, + "default_value": null, + "enum": [ + "Error", + "Pending", + "Processing", + "Ready" + ], + "regex": null, + "max_length": null, + "min_length": null, + "read_only": false, + "inherited": false, + "unique": false, + "branch": "local", + "optional": false, + "order_weight": 2000, + "choices": null + }, + { + "id": "179be3f5-ec02-7296-3016-c510fbc0122f", + "name": "content_type", + "kind": "Text", + "namespace": "Attribute", + "label": "Content Type", + "description": null, + "default_value": null, + "enum": [ + "application/json", + "text/plain" + ], + "regex": null, + "max_length": null, + "min_length": null, + "read_only": false, + "inherited": false, + "unique": false, + "branch": "local", + "optional": false, + "order_weight": 3000, + "choices": null + }, + { + "id": "179be3f5-ec73-ae37-301d-c51b20302e14", + "name": "checksum", + "kind": "Text", + "namespace": "Attribute", + "label": "Checksum", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "read_only": false, + "inherited": false, + "unique": false, + "branch": "local", + "optional": true, + "order_weight": 4000, + "choices": null + }, + { + "id": "179be3f5-ece7-c18c-3011-c51a0e3e273e", + "name": "storage_id", + "kind": "Text", + "namespace": "Attribute", + "label": "Storage Id", + "description": "ID of the file in the object store", + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "read_only": false, + "inherited": false, + "unique": false, + "branch": "local", + "optional": true, + "order_weight": 5000, + "choices": null + }, + { + "id": "179be3f5-ed5e-53b7-3011-c5143efc850e", + "name": "parameters", + "kind": "JSON", + "namespace": "Attribute", + "label": "Parameters", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "read_only": false, + "inherited": false, + "unique": false, + "branch": "local", + "optional": true, + "order_weight": 6000, + "choices": null + } + ], + "relationships": [ + { + "id": "179be3f5-edcd-7f06-3011-c51a4a621a7e", + "name": "object", + "peer": "CoreNode", + "kind": "Attribute", + "label": "Object", + "description": null, + "identifier": "artifact__node", + "inherited": false, + "cardinality": "one", + "branch": "local", + "optional": false, + "order_weight": 7000 + }, + { + "id": "179be3f5-ee2d-1349-3013-c517a643565b", + "name": "definition", + "peer": "CoreArtifactDefinition", + "kind": "Attribute", + "label": "Definition", + "description": null, + "identifier": "artifact__artifact_definition", + "inherited": false, + "cardinality": "one", + "branch": "local", + "optional": false, + "order_weight": 8000 + }, + { + "id": "179be3f5-ee86-fd31-301c-c51594ed3876", + "name": "member_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Member Of Groups", + "description": null, + "identifier": "group_member", + "inherited": false, + "cardinality": "many", + "branch": "aware", + "optional": true, + "order_weight": 9000 + }, + { + "id": "179be3f5-eee9-ca52-301d-c5166012d5ce", + "name": "subscriber_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Subscriber Of Groups", + "description": null, + "identifier": "group_subscriber", + "inherited": false, + "cardinality": "many", + "branch": "aware", + "optional": true, + "order_weight": 10000 + } + ], + "include_in_menu": false, + "menu_placement": null, + "icon": null, + "label": "Artifact", + "inherit_from": [], + "kind": "CoreArtifact", + "hash": "eecebc6d23a92ea79a54f8676352ebb5" + }, + { + "id": "1799f63a-5b6b-cb21-304a-c51964ff356c", + "name": "ArtifactDefinition", + "namespace": "Core", + "description": null, + "default_filter": "name__value", + "branch": "aware", + "order_by": [ + "name__value" + ], + "display_labels": [ + "name__value" + ], + "attributes": [ + { + "id": "1799f63a-5bc6-0329-304f-c5133b0a3e09", + "name": "name", + "kind": "Text", + "namespace": "Attribute", + "label": "Name", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": true, + "branch": "aware", + "optional": false, + "order_weight": 1000 + }, + { + "id": "1799f63a-5c26-749d-304a-c5130edc5d10", + "name": "artifact_name", + "kind": "Text", + "namespace": "Attribute", + "label": "Artifact Name", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "aware", + "optional": false, + "order_weight": 2000 + }, + { + "id": "1799f63a-5c85-969e-3048-c5102fe0d7d0", + "name": "description", + "kind": "Text", + "namespace": "Attribute", + "label": "Description", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "aware", + "optional": true, + "order_weight": 3000 + }, + { + "id": "1799f63a-5ce2-84fb-304a-c51541e59ee2", + "name": "parameters", + "kind": "JSON", + "namespace": "Attribute", + "label": "Parameters", + "description": null, + "default_value": null, + "enum": null, + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "aware", + "optional": false, + "order_weight": 4000 + }, + { + "id": "1799f63a-5d69-d3fa-3049-c51efd44dcbf", + "name": "content_type", + "kind": "Text", + "namespace": "Attribute", + "label": "Content Type", + "description": null, + "default_value": null, + "enum": [ + "application/json", + "text/plain" + ], + "regex": null, + "max_length": null, + "min_length": null, + "inherited": false, + "unique": false, + "branch": "aware", + "optional": false, + "order_weight": 5000 + } + ], + "relationships": [ + { + "id": "1799f63a-5dd2-3fc0-3046-c51b909b6a36", + "name": "targets", + "peer": "CoreGroup", + "kind": "Attribute", + "label": "Targets", + "description": null, + "identifier": "artifact_definition___group", + "inherited": false, + "cardinality": "one", + "branch": "aware", + "optional": false, + "order_weight": 6000 + }, + { + "id": "1799f63a-5e27-e84c-3046-c514bd181b05", + "name": "transformation", + "peer": "CoreTransformation", + "kind": "Attribute", + "label": "Transformation", + "description": null, + "identifier": "artifact_definition___transformation", + "inherited": false, + "cardinality": "one", + "branch": "aware", + "optional": false, + "order_weight": 7000 + }, + { + "id": "1799f63a-5e7d-5a28-3048-c51eb5055587", + "name": "member_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Member Of Groups", + "description": null, + "identifier": "group_member", + "inherited": false, + "cardinality": "many", + "branch": "aware", + "optional": true, + "order_weight": 8000 + }, + { + "id": "1799f63a-5ed0-c577-3048-c512f9ff312a", + "name": "subscriber_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Subscriber Of Groups", + "description": null, + "identifier": "group_subscriber", + "inherited": false, + "cardinality": "many", + "branch": "aware", + "optional": true, + "order_weight": 9000 + } + ], + "include_in_menu": false, + "menu_placement": null, + "icon": null, + "label": "Artifact Definition", + "inherit_from": [], + "kind": "CoreArtifactDefinition" } - ], - "include_in_menu": false, - "menu_placement": null, - "icon": null, - "label": "Artifact Definition", - "inherit_from": [], - "kind": "CoreArtifactDefinition" - } - ], - "generics": [] -} + ], + "generics": [] +} \ No newline at end of file diff --git a/tests/fixtures/schema_ipam.json b/tests/fixtures/schema_ipam.json index 5f022625..4c99b72d 100644 --- a/tests/fixtures/schema_ipam.json +++ b/tests/fixtures/schema_ipam.json @@ -23,4112 +23,530 @@ ], "uniqueness_constraints": null, "documentation": null, - "filters": [ + "attributes": [ { - "id": null, + "id": "17d9bd6f-6523-88d0-2788-179f06f96513", "state": "present", - "name": "ids", - "kind": "Text", + "name": "prefix", + "kind": "IPNetwork", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Prefix", + "description": null, + "read_only": false, + "unique": false, + "optional": false, + "branch": "aware", + "order_weight": 1000, + "default_value": null, + "inherited": true, + "allow_override": "any" }, { - "id": null, + "id": "17d9bd6f-656d-9da8-2781-179fb3e12549", "state": "present", - "name": "prefix__value", + "name": "description", "kind": "Text", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Description", + "description": null, + "read_only": false, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 2000, + "default_value": null, + "inherited": true, + "allow_override": "any" }, { - "id": null, + "id": "17d9bd6f-65bc-5dd0-278f-179f9ae80795", "state": "present", - "name": "description__value", - "kind": "Text", + "name": "member_type", + "kind": "Dropdown", "enum": null, - "object_kind": null, - "description": null + "choices": [ + { + "id": null, + "state": "present", + "name": "prefix", + "description": "Prefix serves as container for other prefixes", + "color": "#ed6a5a", + "label": "Prefix" + }, + { + "id": null, + "state": "present", + "name": "address", + "description": "Prefix serves as subnet for IP addresses", + "color": "#f4f1bb", + "label": "Address" + } + ], + "regex": null, + "max_length": null, + "min_length": null, + "label": "Member Type", + "description": null, + "read_only": false, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 3000, + "default_value": "address", + "inherited": true, + "allow_override": "any" }, { - "id": null, + "id": "17d9bd6f-6609-5108-2787-179fc10e797a", "state": "present", - "name": "description__values", - "kind": "Text", + "name": "is_pool", + "kind": "Boolean", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Is Pool", + "description": "All IP addresses within this prefix are considered usable", + "read_only": false, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 4000, + "default_value": false, + "inherited": true, + "allow_override": "any" }, { - "id": null, + "id": "17d9bd6f-6657-9fe8-278b-179f7fcff935", "state": "present", - "name": "description__is_visible", + "name": "is_top_level", "kind": "Boolean", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Is Top Level", + "description": null, + "read_only": true, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 5000, + "default_value": null, + "inherited": true, + "allow_override": "none" }, { - "id": null, + "id": "17d9bd6f-66a4-54a0-2782-179fd2a0a7a2", "state": "present", - "name": "description__is_protected", - "kind": "Boolean", + "name": "utilization", + "kind": "Number", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Utilization", + "description": null, + "read_only": true, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 6000, + "default_value": null, + "inherited": true, + "allow_override": "none" }, { - "id": null, + "id": "17d9bd6f-6700-b8f8-278c-179f3b309048", "state": "present", - "name": "description__source__id", + "name": "netmask", "kind": "Text", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Netmask", + "description": null, + "read_only": true, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 7000, + "default_value": null, + "inherited": true, + "allow_override": "none" }, { - "id": null, + "id": "17d9bd6f-675c-5a00-278e-179fdb740ee3", "state": "present", - "name": "description__owner__id", + "name": "hostmask", "kind": "Text", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Hostmask", + "description": null, + "read_only": true, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 8000, + "default_value": null, + "inherited": true, + "allow_override": "none" }, { - "id": null, + "id": "17d9bd6f-67ae-7d58-2780-179f5690fd6e", "state": "present", - "name": "member_type__value", + "name": "network_address", "kind": "Text", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Network Address", + "description": null, + "read_only": true, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 9000, + "default_value": null, + "inherited": true, + "allow_override": "none" }, { - "id": null, + "id": "17d9bd6f-67fd-1e40-2782-179f3743d578", "state": "present", - "name": "member_type__values", + "name": "broadcast_address", "kind": "Text", "enum": null, - "object_kind": null, - "description": null - }, + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Broadcast Address", + "description": null, + "read_only": true, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 10000, + "default_value": null, + "inherited": true, + "allow_override": "none" + } + ], + "relationships": [ { - "id": null, + "id": "17d9bd6f-6848-d510-278d-179fdede0e92", "state": "present", - "name": "member_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null + "name": "ip_namespace", + "peer": "BuiltinIPNamespace", + "kind": "Generic", + "label": "IP Namespace", + "description": null, + "identifier": "ip_namespace__ip_prefix", + "cardinality": "one", + "min_count": 0, + "max_count": 1, + "order_weight": 11000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "none", + "read_only": false }, { - "id": null, + "id": "17d9bd6f-6897-5aa0-2783-179ffc129ffd", "state": "present", - "name": "member_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null + "name": "ip_addresses", + "peer": "BuiltinIPAddress", + "kind": "Generic", + "label": "IP Addresses", + "description": null, + "identifier": "ip_prefix__ip_address", + "cardinality": "many", + "min_count": 0, + "max_count": 0, + "order_weight": 12000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "none", + "read_only": true }, { - "id": null, + "id": "17d9bd6f-68e6-5560-278f-179fe7a245e5", "state": "present", - "name": "member_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null + "name": "member_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Member Of Groups", + "description": null, + "identifier": "group_member", + "cardinality": "many", + "min_count": 0, + "max_count": 0, + "order_weight": 13000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "any", + "read_only": false }, { - "id": null, + "id": "17d9bd6f-6936-26f8-278a-179fc817723d", "state": "present", - "name": "member_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null + "name": "subscriber_of_groups", + "peer": "CoreGroup", + "kind": "Group", + "label": "Subscriber Of Groups", + "description": null, + "identifier": "group_subscriber", + "cardinality": "many", + "min_count": 0, + "max_count": 0, + "order_weight": 14000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "any", + "read_only": false }, { - "id": null, + "id": "17d9bd6f-6989-2128-278c-179f2b57e70f", "state": "present", - "name": "utilization__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null + "name": "parent", + "peer": "BuiltinIPPrefix", + "kind": "Hierarchy", + "label": "Parent", + "description": null, + "identifier": "parent__child", + "cardinality": "one", + "min_count": 0, + "max_count": 1, + "order_weight": 15000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "outbound", + "hierarchical": "BuiltinIPPrefix", + "on_delete": "no-action", + "allow_override": "any", + "read_only": true }, { - "id": null, + "id": "17d9bd6f-69e3-c060-278c-179fdbe91d53", "state": "present", - "name": "utilization__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null + "name": "children", + "peer": "BuiltinIPPrefix", + "kind": "Hierarchy", + "label": "Children", + "description": null, + "identifier": "parent__child", + "cardinality": "many", + "min_count": 0, + "max_count": 0, + "order_weight": 16000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "inbound", + "hierarchical": "BuiltinIPPrefix", + "on_delete": "no-action", + "allow_override": "any", + "read_only": true }, { - "id": null, + "id": "17d9bd6f-6a36-35c0-278b-179f6cb47e47", "state": "present", - "name": "utilization__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, + "name": "profiles", + "peer": "ProfileIpamIPPrefix", + "kind": "Profile", + "label": "Profiles", + "description": null, + "identifier": "node__profile", + "cardinality": "many", + "min_count": 0, + "max_count": 0, + "order_weight": 17000, + "optional": true, + "branch": "aware", + "inherited": false, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "any", + "read_only": false + } + ], + "inherit_from": [ + "BuiltinIPPrefix" + ], + "generate_profile": true, + "hierarchy": "BuiltinIPPrefix", + "parent": "BuiltinIPPrefix", + "children": "BuiltinIPPrefix", + "kind": "IpamIPPrefix", + "hash": "e32f68b67633af054d23e35b4dd1a5e6" + }, + { + "id": "17d9bd6f-6185-cc88-278c-179fd6360c8d", + "state": "present", + "name": "IPAddress", + "namespace": "Ipam", + "description": "IP Address", + "label": "IP Address", + "branch": "aware", + "default_filter": "address__value", + "human_friendly_id": null, + "display_labels": [ + "address__value" + ], + "include_in_menu": false, + "menu_placement": null, + "icon": "mdi:ip-outline", + "order_by": [ + "address__version", + "address__binary_address" + ], + "uniqueness_constraints": null, + "documentation": null, + "attributes": [ { - "id": null, + "id": "17d9bd6f-61e5-1710-2785-179f38d20caf", "state": "present", - "name": "netmask__value", - "kind": "Text", + "name": "address", + "kind": "IPHost", "enum": null, - "object_kind": null, - "description": null + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Address", + "description": null, + "read_only": false, + "unique": false, + "optional": false, + "branch": "aware", + "order_weight": 1000, + "default_value": null, + "inherited": true, + "allow_override": "any" }, { - "id": null, + "id": "17d9bd6f-6240-9cc0-2783-179f8eb17542", "state": "present", - "name": "netmask__values", + "name": "description", "kind": "Text", "enum": null, - "object_kind": null, - "description": null - }, + "choices": null, + "regex": null, + "max_length": null, + "min_length": null, + "label": "Description", + "description": null, + "read_only": false, + "unique": false, + "optional": true, + "branch": "aware", + "order_weight": 2000, + "default_value": null, + "inherited": true, + "allow_override": "any" + } + ], + "relationships": [ { - "id": null, + "id": "17d9bd6f-6295-2178-2783-179f5df1a9f6", "state": "present", - "name": "netmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null + "name": "interface", + "peer": "InfraInterfaceL3", + "kind": "Generic", + "label": "Interface", + "description": null, + "identifier": "infrainterfacel3__ipamipaddress", + "cardinality": "one", + "min_count": 0, + "max_count": 1, + "order_weight": 3000, + "optional": true, + "branch": "aware", + "inherited": false, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "any", + "read_only": false }, { - "id": null, + "id": "17d9bd6f-62f4-25b0-278b-179faf71de7c", "state": "present", - "name": "netmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "attributes": [ - { - "id": "17d9bd6f-6523-88d0-2788-179f06f96513", - "state": "present", - "name": "prefix", - "kind": "IPNetwork", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Prefix", - "description": null, - "read_only": false, - "unique": false, - "optional": false, - "branch": "aware", - "order_weight": 1000, - "default_value": null, - "inherited": true, - "allow_override": "any" - }, - { - "id": "17d9bd6f-656d-9da8-2781-179fb3e12549", - "state": "present", - "name": "description", - "kind": "Text", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Description", - "description": null, - "read_only": false, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 2000, - "default_value": null, - "inherited": true, - "allow_override": "any" - }, - { - "id": "17d9bd6f-65bc-5dd0-278f-179f9ae80795", - "state": "present", - "name": "member_type", - "kind": "Dropdown", - "enum": null, - "choices": [ - { - "id": null, - "state": "present", - "name": "prefix", - "description": "Prefix serves as container for other prefixes", - "color": "#ed6a5a", - "label": "Prefix" - }, - { - "id": null, - "state": "present", - "name": "address", - "description": "Prefix serves as subnet for IP addresses", - "color": "#f4f1bb", - "label": "Address" - } - ], - "regex": null, - "max_length": null, - "min_length": null, - "label": "Member Type", - "description": null, - "read_only": false, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 3000, - "default_value": "address", - "inherited": true, - "allow_override": "any" - }, - { - "id": "17d9bd6f-6609-5108-2787-179fc10e797a", - "state": "present", - "name": "is_pool", - "kind": "Boolean", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Is Pool", - "description": "All IP addresses within this prefix are considered usable", - "read_only": false, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 4000, - "default_value": false, - "inherited": true, - "allow_override": "any" - }, - { - "id": "17d9bd6f-6657-9fe8-278b-179f7fcff935", - "state": "present", - "name": "is_top_level", - "kind": "Boolean", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Is Top Level", - "description": null, - "read_only": true, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 5000, - "default_value": null, - "inherited": true, - "allow_override": "none" - }, - { - "id": "17d9bd6f-66a4-54a0-2782-179fd2a0a7a2", - "state": "present", - "name": "utilization", - "kind": "Number", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Utilization", - "description": null, - "read_only": true, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 6000, - "default_value": null, - "inherited": true, - "allow_override": "none" - }, - { - "id": "17d9bd6f-6700-b8f8-278c-179f3b309048", - "state": "present", - "name": "netmask", - "kind": "Text", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Netmask", - "description": null, - "read_only": true, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 7000, - "default_value": null, - "inherited": true, - "allow_override": "none" - }, - { - "id": "17d9bd6f-675c-5a00-278e-179fdb740ee3", - "state": "present", - "name": "hostmask", - "kind": "Text", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Hostmask", - "description": null, - "read_only": true, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 8000, - "default_value": null, - "inherited": true, - "allow_override": "none" - }, - { - "id": "17d9bd6f-67ae-7d58-2780-179f5690fd6e", - "state": "present", - "name": "network_address", - "kind": "Text", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Network Address", - "description": null, - "read_only": true, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 9000, - "default_value": null, - "inherited": true, - "allow_override": "none" - }, - { - "id": "17d9bd6f-67fd-1e40-2782-179f3743d578", - "state": "present", - "name": "broadcast_address", - "kind": "Text", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Broadcast Address", - "description": null, - "read_only": true, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 10000, - "default_value": null, - "inherited": true, - "allow_override": "none" - } - ], - "relationships": [ - { - "id": "17d9bd6f-6848-d510-278d-179fdede0e92", - "state": "present", - "name": "ip_namespace", - "peer": "BuiltinIPNamespace", - "kind": "Generic", - "label": "IP Namespace", - "description": null, - "identifier": "ip_namespace__ip_prefix", - "cardinality": "one", - "min_count": 0, - "max_count": 1, - "order_weight": 11000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "none", - "read_only": false - }, - { - "id": "17d9bd6f-6897-5aa0-2783-179ffc129ffd", - "state": "present", - "name": "ip_addresses", - "peer": "BuiltinIPAddress", - "kind": "Generic", - "label": "IP Addresses", - "description": null, - "identifier": "ip_prefix__ip_address", - "cardinality": "many", - "min_count": 0, - "max_count": 0, - "order_weight": 12000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "none", - "read_only": true - }, - { - "id": "17d9bd6f-68e6-5560-278f-179fe7a245e5", - "state": "present", - "name": "member_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Member Of Groups", - "description": null, - "identifier": "group_member", - "cardinality": "many", - "min_count": 0, - "max_count": 0, - "order_weight": 13000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "any", - "read_only": false - }, - { - "id": "17d9bd6f-6936-26f8-278a-179fc817723d", - "state": "present", - "name": "subscriber_of_groups", - "peer": "CoreGroup", - "kind": "Group", - "label": "Subscriber Of Groups", - "description": null, - "identifier": "group_subscriber", - "cardinality": "many", - "min_count": 0, - "max_count": 0, - "order_weight": 14000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "any", - "read_only": false - }, - { - "id": "17d9bd6f-6989-2128-278c-179f2b57e70f", - "state": "present", - "name": "parent", - "peer": "BuiltinIPPrefix", - "kind": "Hierarchy", - "label": "Parent", - "description": null, - "identifier": "parent__child", - "cardinality": "one", - "min_count": 0, - "max_count": 1, - "order_weight": 15000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "outbound", - "hierarchical": "BuiltinIPPrefix", - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "any", - "read_only": true - }, - { - "id": "17d9bd6f-69e3-c060-278c-179fdbe91d53", - "state": "present", - "name": "children", - "peer": "BuiltinIPPrefix", - "kind": "Hierarchy", - "label": "Children", - "description": null, - "identifier": "parent__child", - "cardinality": "many", - "min_count": 0, - "max_count": 0, - "order_weight": 16000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "inbound", - "hierarchical": "BuiltinIPPrefix", - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "any", - "read_only": true - }, - { - "id": "17d9bd6f-6a36-35c0-278b-179f6cb47e47", - "state": "present", - "name": "profiles", - "peer": "ProfileIpamIPPrefix", - "kind": "Profile", - "label": "Profiles", - "description": null, - "identifier": "node__profile", - "cardinality": "many", - "min_count": 0, - "max_count": 0, - "order_weight": 17000, - "optional": true, - "branch": "aware", - "inherited": false, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "any", - "read_only": false - } - ], - "inherit_from": [ - "BuiltinIPPrefix" - ], - "generate_profile": true, - "hierarchy": "BuiltinIPPrefix", - "parent": "BuiltinIPPrefix", - "children": "BuiltinIPPrefix", - "kind": "IpamIPPrefix", - "hash": "e32f68b67633af054d23e35b4dd1a5e6" - }, - { - "id": "17d9bd6f-6185-cc88-278c-179fd6360c8d", - "state": "present", - "name": "IPAddress", - "namespace": "Ipam", - "description": "IP Address", - "label": "IP Address", - "branch": "aware", - "default_filter": "address__value", - "human_friendly_id": null, - "display_labels": [ - "address__value" - ], - "include_in_menu": false, - "menu_placement": null, - "icon": "mdi:ip-outline", - "order_by": [ - "address__version", - "address__binary_address" - ], - "uniqueness_constraints": null, - "documentation": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "any__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "attributes": [ - { - "id": "17d9bd6f-61e5-1710-2785-179f38d20caf", - "state": "present", - "name": "address", - "kind": "IPHost", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Address", - "description": null, - "read_only": false, - "unique": false, - "optional": false, - "branch": "aware", - "order_weight": 1000, - "default_value": null, - "inherited": true, - "allow_override": "any" - }, - { - "id": "17d9bd6f-6240-9cc0-2783-179f8eb17542", - "state": "present", - "name": "description", - "kind": "Text", - "enum": null, - "choices": null, - "regex": null, - "max_length": null, - "min_length": null, - "label": "Description", - "description": null, - "read_only": false, - "unique": false, - "optional": true, - "branch": "aware", - "order_weight": 2000, - "default_value": null, - "inherited": true, - "allow_override": "any" - } - ], - "relationships": [ - { - "id": "17d9bd6f-6295-2178-2783-179f5df1a9f6", - "state": "present", - "name": "interface", - "peer": "InfraInterfaceL3", - "kind": "Generic", - "label": "Interface", - "description": null, - "identifier": "infrainterfacel3__ipamipaddress", - "cardinality": "one", - "min_count": 0, - "max_count": 1, - "order_weight": 3000, - "optional": true, - "branch": "aware", - "inherited": false, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_rate__value", - "kind": "Text", - "enum": [ - "Fast", - "Normal" - ], - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_rate__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_rate__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_rate__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_rate__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_rate__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_priority__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_priority__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_priority__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_priority__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_priority__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "lacp_priority__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "speed__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "speed__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "speed__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "speed__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "speed__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "speed__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "mtu__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "mtu__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "mtu__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "mtu__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "mtu__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "mtu__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "enabled__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "enabled__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "enabled__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "enabled__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "enabled__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "enabled__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "status__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "status__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "status__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "status__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "status__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "status__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "role__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "role__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "role__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "role__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "role__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "role__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "any", - "read_only": false - }, - { - "id": "17d9bd6f-62f4-25b0-278b-179faf71de7c", - "state": "present", - "name": "ip_namespace", - "peer": "BuiltinIPNamespace", - "kind": "Generic", - "label": "IP Namespace", - "description": null, - "identifier": "ip_namespace__ip_address", - "cardinality": "one", - "min_count": 0, - "max_count": 1, - "order_weight": 3000, - "optional": true, - "branch": "aware", - "inherited": true, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], - "on_delete": "no-action", - "allow_override": "none", - "read_only": false - }, - { - "id": "17d9bd6f-634e-5f58-2782-179fcb00ad84", - "state": "present", - "name": "ip_prefix", - "peer": "BuiltinIPPrefix", + "name": "ip_namespace", + "peer": "BuiltinIPNamespace", "kind": "Generic", - "label": "IP Prefix", + "label": "IP Namespace", "description": null, - "identifier": "ip_prefix__ip_address", + "identifier": "ip_namespace__ip_address", "cardinality": "one", "min_count": 0, "max_count": 1, - "order_weight": 4000, + "order_weight": 3000, "optional": true, "branch": "aware", - "inherited": true, - "direction": "bidirectional", - "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "member_type__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_pool__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__value", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "is_top_level__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "utilization__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "netmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "hostmask__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "network_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "broadcast_address__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], + "inherited": true, + "direction": "bidirectional", + "hierarchical": null, + "on_delete": "no-action", + "allow_override": "none", + "read_only": false + }, + { + "id": "17d9bd6f-634e-5f58-2782-179fcb00ad84", + "state": "present", + "name": "ip_prefix", + "peer": "BuiltinIPPrefix", + "kind": "Generic", + "label": "IP Prefix", + "description": null, + "identifier": "ip_prefix__ip_address", + "cardinality": "one", + "min_count": 0, + "max_count": 1, + "order_weight": 4000, + "optional": true, + "branch": "aware", + "inherited": true, + "direction": "bidirectional", + "hierarchical": null, "on_delete": "no-action", "allow_override": "none", "read_only": true @@ -4151,179 +569,6 @@ "inherited": true, "direction": "bidirectional", "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], "on_delete": "no-action", "allow_override": "any", "read_only": false @@ -4346,179 +591,6 @@ "inherited": true, "direction": "bidirectional", "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "label__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], "on_delete": "no-action", "allow_override": "any", "read_only": false @@ -4541,179 +613,6 @@ "inherited": false, "direction": "bidirectional", "hierarchical": null, - "filters": [ - { - "id": null, - "state": "present", - "name": "ids", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_name__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__value", - "kind": "Number", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "profile_priority__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__value", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__values", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_visible", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__is_protected", - "kind": "Boolean", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__source__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - }, - { - "id": null, - "state": "present", - "name": "description__owner__id", - "kind": "Text", - "enum": null, - "object_kind": null, - "description": null - } - ], "on_delete": "no-action", "allow_override": "any", "read_only": false diff --git a/tests/integration/test_export_import.py b/tests/integration/test_export_import.py index df2247b6..cd2931bc 100644 --- a/tests/integration/test_export_import.py +++ b/tests/integration/test_export_import.py @@ -409,7 +409,7 @@ def schema(self, schema_car_base, schema_pool_base, schema_manufacturer_base) -> } @pytest.fixture(scope="class") - async def initial_dataset(self, client: InfrahubClient, schema): # noqa: PLR0914 + async def initial_dataset(self, client: InfrahubClient, schema): await client.schema.load(schemas=[schema]) bmw = await client.create( diff --git a/tests/integration/test_object_store.py b/tests/integration/test_object_store.py index 3da9d57f..5296cb97 100644 --- a/tests/integration/test_object_store.py +++ b/tests/integration/test_object_store.py @@ -11,7 +11,7 @@ class TestObjectStore(TestInfrahubApp): async def test_upload_and_get(self, client: InfrahubClient): response = await client.object_store.upload(content=FILE_CONTENT_01) - assert sorted(list(response.keys())) == ["checksum", "identifier"] + assert sorted(response.keys()) == ["checksum", "identifier"] assert response["checksum"] == "aa19b96860ec59a73906dd8660bb3bad" assert response["identifier"] diff --git a/tests/unit/ctl/test_validate_app.py b/tests/unit/ctl/test_validate_app.py index 19931817..43d41ddb 100644 --- a/tests/unit/ctl/test_validate_app.py +++ b/tests/unit/ctl/test_validate_app.py @@ -21,7 +21,7 @@ def test_validate_schema_empty(): result = runner.invoke(app=app, args=["schema", str(fixture_file)]) assert result.exit_code == 1 - assert "'version' | Field required (missing)" in remove_ansi_color(result.stdout) + assert "Empty YAML/JSON file" in remove_ansi_color(result.stdout) def test_validate_schema_non_valid(): diff --git a/tests/unit/sdk/test_batch.py b/tests/unit/sdk/test_batch.py index a6cba3a5..83beaa53 100644 --- a/tests/unit/sdk/test_batch.py +++ b/tests/unit/sdk/test_batch.py @@ -1,11 +1,19 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + import pytest -from pytest_httpx import HTTPXMock from infrahub_sdk.exceptions import GraphQLError +if TYPE_CHECKING: + from pytest_httpx import HTTPXMock + + from tests.unit.sdk.conftest import BothClients + async def test_batch_return_exception( - httpx_mock: HTTPXMock, mock_query_mutation_location_create_failed, mock_schema_query_01, clients + httpx_mock: HTTPXMock, mock_query_mutation_location_create_failed, mock_schema_query_01, clients: BothClients ): # pylint: disable=unused-argument batch = await clients.standard.create_batch(return_exceptions=True) locations = ["JFK1", "JFK1"] @@ -30,7 +38,7 @@ async def test_batch_return_exception( async def test_batch_exception( - httpx_mock: HTTPXMock, mock_query_mutation_location_create_failed, mock_schema_query_01, clients + httpx_mock: HTTPXMock, mock_query_mutation_location_create_failed, mock_schema_query_01, clients: BothClients ): # pylint: disable=unused-argument batch = await clients.standard.create_batch(return_exceptions=False) locations = ["JFK1", "JFK1"] @@ -40,11 +48,11 @@ async def test_batch_exception( batch.add(task=obj.save, node=obj) with pytest.raises(GraphQLError) as exc: - async for node, result in batch.execute(): + async for _, _ in batch.execute(): pass assert "An error occurred while executing the GraphQL Query" in str(exc.value) -async def test_batch_not_implemented_sync(clients): +async def test_batch_not_implemented_sync(clients: BothClients): with pytest.raises(NotImplementedError): clients.sync.create_batch() diff --git a/tests/unit/sdk/test_data/schema_encoding_error.yml b/tests/unit/sdk/test_data/schema_encoding_error.yml new file mode 100644 index 00000000..1b211472 Binary files /dev/null and b/tests/unit/sdk/test_data/schema_encoding_error.yml differ diff --git a/tests/unit/sdk/test_node.py b/tests/unit/sdk/test_node.py index 5749052d..12ab305b 100644 --- a/tests/unit/sdk/test_node.py +++ b/tests/unit/sdk/test_node.py @@ -1309,10 +1309,10 @@ async def test_node_get_relationship_not_in_store(client, location_schema, locat node = InfrahubNodeSync(client=client, schema=location_schema, data=location_data01) with pytest.raises(NodeNotFoundError): - node.primary_tag.peer # pylint: disable=pointless-statement + _ = node.primary_tag.peer with pytest.raises(NodeNotFoundError): - node.tags[0].peer # pylint: disable=pointless-statement + _ = node.tags[0].peer @pytest.mark.parametrize("client_type", client_types) diff --git a/tests/unit/sdk/test_schema.py b/tests/unit/sdk/test_schema.py index 2a39fdb2..0d46f8f6 100644 --- a/tests/unit/sdk/test_schema.py +++ b/tests/unit/sdk/test_schema.py @@ -5,9 +5,9 @@ import pytest from rich.console import Console -from infrahub_sdk import Config, InfrahubClient, InfrahubClientSync, ValidationError +from infrahub_sdk import Config, InfrahubClient, InfrahubClientSync from infrahub_sdk.ctl.schema import display_schema_load_errors -from infrahub_sdk.exceptions import SchemaNotFoundError +from infrahub_sdk.exceptions import SchemaNotFoundError, ValidationError from infrahub_sdk.schema import ( InfrahubCheckDefinitionConfig, InfrahubJinja2TransformConfig, @@ -77,7 +77,7 @@ async def test_schema_data_validation(rfile_schema, client_type): schema=rfile_schema, data={"name": "some-name", "invalid_field": "yes"} ) - assert "invalid_field is not a valid value for CoreTransformJinja2" == excinfo.value.message + assert excinfo.value.message == "invalid_field is not a valid value for CoreTransformJinja2" @pytest.mark.parametrize("client_type", client_types) @@ -310,5 +310,5 @@ async def test_display_schema_load_errors_details_namespace(mock_get_node): output = console.file.getvalue() expected_console = """Unable to load the schema: Node: OuTInstance | namespace (OuT) | String should match pattern '^[A-Z]+$' (string_pattern_mismatch) -""" # noqa: E501 +""" assert output == expected_console diff --git a/tests/unit/sdk/test_store.py b/tests/unit/sdk/test_store.py index ea298b39..3d02bb32 100644 --- a/tests/unit/sdk/test_store.py +++ b/tests/unit/sdk/test_store.py @@ -1,6 +1,7 @@ import pytest -from infrahub_sdk import InfrahubNode, NodeStore +from infrahub_sdk.node import InfrahubNode +from infrahub_sdk.store import NodeStore client_types = ["standard", "sync"] diff --git a/tests/unit/sdk/test_yaml.py b/tests/unit/sdk/test_yaml.py new file mode 100644 index 00000000..8c2b9654 --- /dev/null +++ b/tests/unit/sdk/test_yaml.py @@ -0,0 +1,21 @@ +from pathlib import Path + +from infrahub_sdk.yaml import YamlFile + +here = Path(__file__).parent.resolve() + + +def test_read_missing_file() -> None: + file = here / "test_data/i_do_not_exist.yml" + yaml_file = YamlFile(location=file) + yaml_file.load_content() + assert not yaml_file.valid + assert yaml_file.error_message == f"{file} is not a valid file" + + +def test_read_incorrect_encoding() -> None: + file = here / "test_data/schema_encoding_error.yml" + yaml_file = YamlFile(location=file) + yaml_file.load_content() + assert not yaml_file.valid + assert yaml_file.error_message == f"Unable to read {file} with utf-8 encoding"