Skip to content

Commit

Permalink
ADCM-6210 Test on Action API
Browse files Browse the repository at this point in the history
  • Loading branch information
Sealwing committed Dec 26, 2024
1 parent 373f2a0 commit 65d2d8f
Show file tree
Hide file tree
Showing 25 changed files with 281 additions and 73 deletions.
7 changes: 5 additions & 2 deletions adcm_aio_client/core/actions/_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,15 @@ class UpgradeNode[Parent: InteractiveObject](NonPaginatedChildAccessor[Parent, U


async def detect_cluster(owner: InteractiveObject) -> Cluster:
from adcm_aio_client.core.objects.cm import Cluster, Component, Host, Service
from adcm_aio_client.core.objects.cm import ActionHostGroup, Cluster, Component, Host, Service

if isinstance(owner, ActionHostGroup):
return await detect_cluster(owner._parent)

if isinstance(owner, Cluster):
return owner

if isinstance(owner, (Service, Component)):
if isinstance(owner, Service | Component):
return owner.cluster

if isinstance(owner, Host):
Expand Down
3 changes: 2 additions & 1 deletion adcm_aio_client/core/config/_objects.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from collections.abc import Callable, Coroutine
from copy import deepcopy
from functools import partial
from typing import Any, Callable, Coroutine, Protocol, Self, overload
from typing import Any, Protocol, Self, overload
import json
import asyncio

Expand Down
3 changes: 2 additions & 1 deletion adcm_aio_client/core/config/types.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from abc import ABC
from collections import defaultdict
from collections.abc import Callable, Iterable
from dataclasses import dataclass, field
from functools import reduce
from typing import Any, Callable, Iterable, NamedTuple, Protocol, Self
from typing import Any, NamedTuple, Protocol, Self

# External Section
# these functions are heavily inspired by configuration rework in ADCM (ADCM-6034)
Expand Down
7 changes: 4 additions & 3 deletions adcm_aio_client/core/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
# limitations under the License.

from collections import deque
from collections.abc import Generator, Iterable
from dataclasses import dataclass
from typing import Generator, Iterable, Self
from typing import Self

from adcm_aio_client.core.errors import InvalidFilterError
from adcm_aio_client.core.objects._base import InteractiveObject
Expand Down Expand Up @@ -114,7 +115,7 @@ def _attribute_name_to_camel_case(self: Self, name: str) -> str:
return f"{first}{''.join(map(str.capitalize, rest))}"

def _simplify_value(self: Self, value: FilterValue) -> SimplifiedValue:
if isinstance(value, (str, int)):
if isinstance(value, str | int):
return value

if isinstance(value, InteractiveObject):
Expand All @@ -123,7 +124,7 @@ def _simplify_value(self: Self, value: FilterValue) -> SimplifiedValue:
simplified_collection = deque()

for entry in value:
if isinstance(entry, (str, int)):
if isinstance(entry, str | int):
simplified_collection.append(entry)
elif isinstance(entry, InteractiveObject):
simplified_collection.append(entry.id)
Expand Down
3 changes: 2 additions & 1 deletion adcm_aio_client/core/host_groups/_common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from collections.abc import Iterable
from functools import partial
from typing import TYPE_CHECKING, Any, Iterable, Self, Union
from typing import TYPE_CHECKING, Any, Self, Union

from adcm_aio_client.core.filters import Filter
from adcm_aio_client.core.objects._accessors import (
Expand Down
4 changes: 2 additions & 2 deletions adcm_aio_client/core/mapping/_objects.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations

from collections.abc import Generator
from collections.abc import Callable, Coroutine, Generator, Iterable
from copy import copy
from functools import cached_property
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Iterable, Self
from typing import TYPE_CHECKING, Any, Self
import asyncio

from adcm_aio_client.core.filters import Filter, FilterByDisplayName, FilterByName, FilterByStatus, Filtering
Expand Down
3 changes: 2 additions & 1 deletion adcm_aio_client/core/objects/_accessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
# limitations under the License.

from abc import ABC, abstractmethod
from collections.abc import AsyncGenerator
from contextlib import suppress
from typing import Any, AsyncGenerator, Self
from typing import Any, Self

from adcm_aio_client.core.errors import MultipleObjectsReturnedError, ObjectDoesNotExistError
from adcm_aio_client.core.filters import Filter, Filtering, FilterValue
Expand Down
2 changes: 1 addition & 1 deletion adcm_aio_client/core/objects/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init_subclass__(cls: type[Self]) -> None:
for name in dir(cls):
# None is for declared, but unset values
attr = getattr(cls, name, None)
if isinstance(attr, (cached_property, CachedProperty)):
if isinstance(attr, cached_property | CachedProperty):
cls._delete_on_refresh.append(name)

def __init__(self: Self, requester: Requester, data: dict[str, Any]) -> None:
Expand Down
3 changes: 2 additions & 1 deletion adcm_aio_client/core/objects/_imports.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import TYPE_CHECKING, Collection, Iterable, Self, Union
from collections.abc import Collection, Iterable
from typing import TYPE_CHECKING, Self, Union

from adcm_aio_client.core.types import Endpoint, Requester

Expand Down
5 changes: 3 additions & 2 deletions adcm_aio_client/core/objects/cm.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from collections import deque
from collections.abc import AsyncGenerator, Awaitable, Callable, Iterable
from datetime import datetime, timedelta
from functools import cached_property
from pathlib import Path
from typing import Any, AsyncGenerator, Awaitable, Callable, Iterable, Literal, Self
from typing import Any, Literal, Self
import asyncio

from asyncstdlib.functools import cached_property as async_cached_property # noqa: N813
Expand Down Expand Up @@ -628,7 +629,7 @@ def _prepare_filter_by_object(self: Self, object_: InteractiveObject | None) ->

object_id = object_.id

if isinstance(object_, (Cluster, Service, Component, Host)):
if isinstance(object_, Cluster | Service | Component | Host):
object_type = object_.__class__.__name__.lower()
elif isinstance(object_, HostProvider):
object_type = "provider"
Expand Down
9 changes: 5 additions & 4 deletions adcm_aio_client/core/requesters.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
# limitations under the License.
from abc import ABC, abstractmethod
from asyncio import sleep
from collections.abc import Awaitable, Callable, Coroutine
from contextlib import suppress
from dataclasses import dataclass
from functools import wraps
from json.decoder import JSONDecodeError
from typing import Any, Awaitable, Callable, Coroutine, ParamSpec, Self, TypeAlias
from typing import Any, ParamSpec, Self, TypeAlias
from urllib.parse import urljoin

import httpx
Expand Down Expand Up @@ -46,10 +47,10 @@
URLStr,
)

Json: TypeAlias = Any
Json: TypeAlias = Any # noqa: UP040
Params = ParamSpec("Params")
RequestFunc: TypeAlias = Callable[Params, Awaitable["HTTPXRequesterResponse"]]
DoRequestFunc: TypeAlias = Callable[Params, Awaitable[httpx.Response]]
RequestFunc: TypeAlias = Callable[Params, Awaitable["HTTPXRequesterResponse"]] # noqa: UP040
DoRequestFunc: TypeAlias = Callable[Params, Awaitable[httpx.Response]] # noqa: UP040


@dataclass(slots=True)
Expand Down
4 changes: 2 additions & 2 deletions adcm_aio_client/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

from dataclasses import asdict, dataclass
from enum import Enum
from typing import Optional, Protocol, Self
from typing import Protocol, Self

# Init / Authorization

type AuthToken = str
type Cert = str | tuple[str, Optional[str], Optional[str]]
type Cert = str | tuple[str, str | None, str | None]
type Verify = str | bool


Expand Down
2 changes: 1 addition & 1 deletion adcm_aio_client/core/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Awaitable, Iterable
from collections.abc import Awaitable, Iterable
import asyncio

from adcm_aio_client.core.types import RequesterResponse
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ timeout = 300

[tool.ruff]
line-length = 120
target-version = "py312"

[tool.ruff.lint.isort]
force-sort-within-sections = true
Expand Down
18 changes: 17 additions & 1 deletion tests/integration/bundles/complex_cluster/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
display_name: With action, config and mapping
scripts: *upgrade_scripts
config: *upgrade_config
hc_acl:
hc_acl: &hc_acl
- action: add
service: example_1
component: first
Expand Down Expand Up @@ -116,6 +116,22 @@
name: second
display_name: AnothEr

with_config:
<<: *job
display_name: "Configurable one"
config: *upgrade_config

with_mapping:
<<: *job
display_name: "I will change the cluster"
hc_acl: *hc_acl

with_config_and_mapping:
<<: *job
display_name: "JOAT"
config: *upgrade_config
hc_acl: *hc_acl

config:
- name: string_field
type: string
Expand Down
40 changes: 39 additions & 1 deletion tests/integration/bundles/complex_provider/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,49 @@
integer_key: '10'
string_key: string
actions:
provider_action:
provider_action: &job
type: job
script: ./playbook.yaml
script_type: ansible
states:
available: any

with_config: &with_config
<<: *job
display_name: "Configurable one"
config:
- name: string_field
type: string
- name: params
display_name: Some Params
type: group
subs:
- name: cant_find
type: string
default: "cantCme"
ui_options:
invisible: true
- name: pass
type: password
required: no
- name: sag
display_name: Filter
type: structure
yspec: ./sag.yaml
default:
nested:
attr: "nice"
op: "eq"
tech: "true"
quantity: 14443
- name: payload
display_name: Request Body
type: json
default:
- 1
- {"k": "v"}
- "plain"

- type: host
name: host
version: *version
Expand Down Expand Up @@ -87,3 +123,5 @@
script_type: ansible
states:
available: any

with_config: *with_config
19 changes: 19 additions & 0 deletions tests/integration/bundles/complex_provider/sag.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
root:
match: dict
items:
nested: inner_group
quantity: integer

inner_group:
match: dict
items:
attr: string
op: string
tech: string
invisible_items: [ "tech" ]

integer:
match: int

string:
match: string
4 changes: 3 additions & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import AsyncGenerator, Generator
from pathlib import Path
from typing import AsyncGenerator, Generator
from urllib.parse import urljoin
import random
import string
Expand Down Expand Up @@ -71,11 +71,13 @@ async def simple_hostprovider_bundle(adcm_client: ADCMClient, tmp_path: Path) ->
bundle_path = pack_bundle(from_dir=BUNDLES / "simple_hostprovider", to=tmp_path)
return await adcm_client.bundles.create(source=bundle_path, accept_license=True)


@pytest_asyncio.fixture()
async def complex_hostprovider_bundle(adcm_client: ADCMClient, tmp_path: Path) -> Bundle:
bundle_path = pack_bundle(from_dir=BUNDLES / "complex_provider", to=tmp_path)
return await adcm_client.bundles.create(source=bundle_path, accept_license=True)


@pytest_asyncio.fixture()
async def httpx_client(adcm: ADCMContainer) -> AsyncGenerator[AsyncClient, None]:
client = AsyncClient(base_url=urljoin(adcm.url, "api/v2/"))
Expand Down
Loading

0 comments on commit 65d2d8f

Please sign in to comment.