Skip to content

Commit

Permalink
Merge pull request #195 from opsmill/develop
Browse files Browse the repository at this point in the history
Release SDK v1.3.0
  • Loading branch information
lykinsbd authored Dec 30, 2024
2 parents 307ed5e + f99a19e commit 712079b
Show file tree
Hide file tree
Showing 39 changed files with 2,223 additions and 1,571 deletions.
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

0 comments on commit 712079b

Please sign in to comment.