Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1953714
Fix import_root in case a Path object was submitted
ogenstad Dec 20, 2024
0dac001
Merge pull request #181 from opsmill/pog-sys-path
ogenstad Dec 20, 2024
46ceb9f
Cleanup and restructure Pydantic models for Schema
dgarros Dec 1, 2024
0238097
Fix unit tests
dgarros Dec 1, 2024
cb9fe15
Merge pull request #160 from opsmill/dga-20241201-cleanup-schema
dgarros Dec 23, 2024
e4d190f
Add testing directory and infrahub-testcontainers
dgarros Dec 24, 2024
bb2d5e3
Update lock file
dgarros Dec 24, 2024
039a9d9
Adjust format for 3.9
dgarros Dec 24, 2024
fc61aff
Merge pull request #183 from opsmill/dga-20241223-testing
dgarros Dec 24, 2024
479ca16
Fix value from pool for async client (#184)
gmazoyer Dec 28, 2024
ca1a611
Bump DavidAnson/markdownlint-cli2-action from 18 to 19
dependabot[bot] Dec 30, 2024
7c9ccd7
Merge pull request #189 from opsmill/dependabot/github_actions/develo…
BeArchiTek Dec 30, 2024
d656daa
Update version for integration tests in test_node.py
dgarros Dec 30, 2024
34337bc
Change pytest plugin to use the same importer as other components
ogenstad Dec 11, 2024
7687e9c
Update pinned version of Jinja2
ogenstad Dec 30, 2024
6af9188
Merge pull request #171 from opsmill/pog-pytest-relative-imports-IHS-72
ogenstad Dec 30, 2024
97388b6
Prep for 1.3 and add release note
dgarros Dec 30, 2024
7b20ecb
Merge pull request #194 from opsmill/pog-update-jinja2
ogenstad Dec 30, 2024
8e560d6
Merge pull request #193 from opsmill/dga-20241230-fix-test-version
dgarros Dec 30, 2024
f99a19e
Merge pull request #186 from opsmill/dga-20241230-rn-1.3
dgarros Dec 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Linting: markdownlint"
uses: DavidAnson/markdownlint-cli2-action@v18
uses: DavidAnson/markdownlint-cli2-action@v19
with:
config: .markdownlint.yaml
globs: |
Expand Down
46 changes: 45 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,50 @@ This project uses [*towncrier*](https://towncrier.readthedocs.io/) and the chang

<!-- towncrier release notes start -->

## [1.3.0](https://github.com/opsmill/infrahub-sdk-python/tree/v1.3.0) - 2024-12-30

### Added

#### Testing library (**Alpha**)

A new collection of tools and utilities to help with testing is available under `infrahub_sdk.testing`.

The first component available is a `TestInfrahubDockerClient`, a pytest Class designed to help creating integration tests based on Infrahub. See a simple example below to help you get started.

> the installation of `infrahub-testcontainers` is required

```python
import pytest

from infrahub_sdk import InfrahubClient
from infrahub_sdk.testing.docker import TestInfrahubDockerClient

class TestInfrahubNode(TestInfrahubDockerClient):

@pytest.fixture(scope="class")
def infrahub_version(self) -> str:
"""Required (for now) to define the version of infrahub to use."""
return "1.0.10"

@pytest.fixture(scope="class")
async def test_create_tag(self, default_branch: str, client: InfrahubClient) -> None:
obj = await client.create(kind="BuiltinTag", name="Blue")
await obj.save()
assert obj.id
```

### Changed

- The Pydantic models for the schema have been split into multiple versions to align better with the different phase of the lifecycle of the schema.
- User input: includes only the options available for a user to define (NodeSchema, AttributeSchema, RelationshipSchema, GenericSchema)
- API: Format of the schema as exposed by the API in infrahub with some read only settings (NodeSchemaAPI, AttributeSchemaAPI, RelationshipSchemaAPI, GenericSchemaAPI)

### Fixed

- Fix behaviour of attribute value coming from resource pools for async client ([#66](https://github.com/opsmill/infrahub-sdk-python/issues/66))
- Convert import_root to a string if it was submitted as a Path object to ensure that anything added to sys.path is a string
- Fix relative imports for the pytest plugin, note that the relative imports can't be at the top level of the repository alongside .infrahub.yml. They have to be located within a subfolder. ([#166](https://github.com/opsmill/infrahub-sdk-python/issues/166))

## [1.2.0](https://github.com/opsmill/infrahub-sdk-python/tree/v1.2.0) - 2024-12-19

### Added
Expand Down Expand Up @@ -60,7 +104,7 @@ This project uses [*towncrier*](https://towncrier.readthedocs.io/) and the chang

### Removed

- 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.
- 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.

### Added

Expand Down
11 changes: 11 additions & 0 deletions infrahub_sdk/_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,23 @@
def import_module(
module_path: Path, import_root: Optional[str] = None, relative_path: Optional[str] = None
) -> ModuleType:
"""Imports a python module.

Args:
module_path (Path): Absolute path of the module to import.
import_root (Optional[str]): Absolute string path to the current repository.
relative_path (Optional[str]): Relative string path between module_path and import_root.
"""
import_root = import_root or str(module_path.parent)

file_on_disk = module_path
if import_root and relative_path:
file_on_disk = Path(import_root, relative_path, module_path.name)

# This is a temporary workaround for to account for issues if "import_root" is a Path instead of a str
# Later we should rework this so that import_root and relative_path are all Path objects. Here we must
# ensure that anything we add to sys.path is a string and not a Path or PosixPath object.
import_root = str(import_root)
if import_root not in sys.path:
sys.path.append(import_root)

Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from pathlib import Path

from . import InfrahubClient
from .schema import InfrahubCheckDefinitionConfig
from .schema.repository import InfrahubCheckDefinitionConfig

INFRAHUB_CHECK_VARIABLE_TO_IMPORT = "INFRAHUB_CHECKS"

Expand Down
10 changes: 5 additions & 5 deletions infrahub_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
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 .schema import InfrahubSchema, InfrahubSchemaSync, NodeSchemaAPI
from .store import NodeStore, NodeStoreSync
from .timestamp import Timestamp
from .types import AsyncRequester, HTTPMethod, SyncRequester
Expand Down Expand Up @@ -448,12 +448,12 @@ async def get(
filters: MutableMapping[str, Any] = {}

if id:
if not is_valid_uuid(id) and isinstance(schema, NodeSchema) and schema.default_filter:
if not is_valid_uuid(id) and isinstance(schema, NodeSchemaAPI) and schema.default_filter:
filters[schema.default_filter] = id
else:
filters["ids"] = [id]
if hfid:
if isinstance(schema, NodeSchema) and schema.human_friendly_id:
if isinstance(schema, NodeSchemaAPI) and schema.human_friendly_id:
filters["hfid"] = hfid
else:
raise ValueError("Cannot filter by HFID if the node doesn't have an HFID defined")
Expand Down Expand Up @@ -1916,12 +1916,12 @@ def get(
filters: MutableMapping[str, Any] = {}

if id:
if not is_valid_uuid(id) and isinstance(schema, NodeSchema) and schema.default_filter:
if not is_valid_uuid(id) and isinstance(schema, NodeSchemaAPI) and schema.default_filter:
filters[schema.default_filter] = id
else:
filters["ids"] = [id]
if hfid:
if isinstance(schema, NodeSchema) and schema.human_friendly_id:
if isinstance(schema, NodeSchemaAPI) and schema.human_friendly_id:
filters["hfid"] = hfid
else:
raise ValueError("Cannot filter by HFID if the node doesn't have an HFID defined")
Expand Down
36 changes: 19 additions & 17 deletions infrahub_sdk/code_generator.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
from collections.abc import Mapping
from typing import Any, Optional
from typing import Any, Optional, Union

import jinja2

from . import protocols as sdk_protocols
from .ctl.constants import PROTOCOLS_TEMPLATE
from .schema import (
AttributeSchema,
AttributeSchemaAPI,
GenericSchema,
MainSchemaTypes,
GenericSchemaAPI,
MainSchemaTypesAll,
NodeSchema,
ProfileSchema,
RelationshipSchema,
NodeSchemaAPI,
ProfileSchemaAPI,
RelationshipSchemaAPI,
)

ATTRIBUTE_KIND_MAP = {
Expand Down Expand Up @@ -40,17 +42,17 @@


class CodeGenerator:
def __init__(self, schema: dict[str, MainSchemaTypes]):
self.generics: dict[str, GenericSchema] = {}
self.nodes: dict[str, NodeSchema] = {}
self.profiles: dict[str, ProfileSchema] = {}
def __init__(self, schema: dict[str, MainSchemaTypesAll]):
self.generics: dict[str, Union[GenericSchemaAPI, GenericSchema]] = {}
self.nodes: dict[str, Union[NodeSchemaAPI, NodeSchema]] = {}
self.profiles: dict[str, ProfileSchemaAPI] = {}

for name, schema_type in schema.items():
if isinstance(schema_type, GenericSchema):
if isinstance(schema_type, (GenericSchemaAPI, GenericSchema)):
self.generics[name] = schema_type
if isinstance(schema_type, NodeSchema):
if isinstance(schema_type, (NodeSchemaAPI, NodeSchema)):
self.nodes[name] = schema_type
if isinstance(schema_type, ProfileSchema):
if isinstance(schema_type, ProfileSchemaAPI):
self.profiles[name] = schema_type

self.base_protocols = [
Expand Down Expand Up @@ -92,7 +94,7 @@ def _jinja2_filter_inheritance(value: dict[str, Any]) -> str:
return ", ".join(inherit_from)

@staticmethod
def _jinja2_filter_render_attribute(value: AttributeSchema) -> str:
def _jinja2_filter_render_attribute(value: AttributeSchemaAPI) -> str:
attribute_kind: str = ATTRIBUTE_KIND_MAP[value.kind]

if value.optional:
Expand All @@ -101,7 +103,7 @@ def _jinja2_filter_render_attribute(value: AttributeSchema) -> str:
return f"{value.name}: {attribute_kind}"

@staticmethod
def _jinja2_filter_render_relationship(value: RelationshipSchema, sync: bool = False) -> str:
def _jinja2_filter_render_relationship(value: RelationshipSchemaAPI, sync: bool = False) -> str:
name = value.name
cardinality = value.cardinality

Expand All @@ -116,12 +118,12 @@ def _jinja2_filter_render_relationship(value: RelationshipSchema, sync: bool = F

@staticmethod
def _sort_and_filter_models(
models: Mapping[str, MainSchemaTypes], filters: Optional[list[str]] = None
) -> list[MainSchemaTypes]:
models: Mapping[str, MainSchemaTypesAll], filters: Optional[list[str]] = None
) -> list[MainSchemaTypesAll]:
if filters is None:
filters = ["CoreNode"]

filtered: list[MainSchemaTypes] = []
filtered: list[MainSchemaTypesAll] = []
for name, model in models.items():
if name in filters:
continue
Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/ctl/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from ..ctl.repository import get_repository_config
from ..ctl.utils import catch_exception, execute_graphql_query
from ..exceptions import ModuleImportError
from ..schema import InfrahubCheckDefinitionConfig, InfrahubRepositoryConfig
from ..schema.repository import InfrahubCheckDefinitionConfig, InfrahubRepositoryConfig

app = typer.Typer()
console = Console()
Expand Down
9 changes: 3 additions & 6 deletions infrahub_sdk/ctl/cli_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,8 @@
from ..ctl.validate import app as validate_app
from ..exceptions import GraphQLError, ModuleImportError
from ..jinja2 import identify_faulty_jinja_code
from ..schema import (
InfrahubRepositoryConfig,
MainSchemaTypes,
SchemaRoot,
)
from ..schema import MainSchemaTypesAll, SchemaRoot
from ..schema.repository import InfrahubRepositoryConfig
from ..utils import get_branch, write_to_file
from ..yaml import SchemaFile
from .exporter import dump
Expand Down Expand Up @@ -364,7 +361,7 @@ def protocols(
) -> None:
"""Export Python protocols corresponding to a schema."""

schema: dict[str, MainSchemaTypes] = {}
schema: dict[str, MainSchemaTypesAll] = {}

if schemas:
schemas_data = load_yamlfile_from_disk_and_exit(paths=schemas, file_type=SchemaFile, console=console)
Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/ctl/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ..ctl.utils import execute_graphql_query, parse_cli_vars
from ..exceptions import ModuleImportError
from ..node import InfrahubNode
from ..schema import InfrahubRepositoryConfig
from ..schema.repository import InfrahubRepositoryConfig


async def run(
Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/ctl/render.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rich.console import Console

from ..schema import InfrahubRepositoryConfig
from ..schema.repository import InfrahubRepositoryConfig


def list_jinja2_transforms(config: InfrahubRepositoryConfig) -> None:
Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/ctl/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ..ctl.exceptions import FileNotValidError
from ..ctl.utils import init_logging
from ..graphql import Mutation
from ..schema import InfrahubRepositoryConfig
from ..schema.repository import InfrahubRepositoryConfig
from ._file import read_file
from .parameters import CONFIG_PARAM

Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/ctl/transform.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rich.console import Console

from ..schema import InfrahubRepositoryConfig
from ..schema.repository import InfrahubRepositoryConfig


def list_transforms(config: InfrahubRepositoryConfig) -> None:
Expand Down
2 changes: 1 addition & 1 deletion infrahub_sdk/ctl/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
ServerNotReachableError,
ServerNotResponsiveError,
)
from ..schema import InfrahubRepositoryConfig
from ..schema.repository import InfrahubRepositoryConfig
from ..yaml import YamlFile
from .client import initialize_client_sync

Expand Down
Loading
Loading