mreg-api 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mreg_api-0.2.0 → mreg_api-0.2.2}/.github/workflows/publish.yml +1 -7
- {mreg_api-0.2.0 → mreg_api-0.2.2}/CHANGELOG.md +26 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/PKG-INFO +1 -1
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/_version.py +3 -3
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/endpoints.py +0 -1
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/models/abstracts.py +40 -97
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/models/fields.py +1 -1
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/models/history.py +2 -1
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/models/models.py +15 -51
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api.egg-info/PKG-INFO +1 -1
- {mreg_api-0.2.0 → mreg_api-0.2.2}/.github/workflows/test.yml +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/.gitignore +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/.markdownlint.json +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/.pre-commit-config.yaml +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/LICENSE +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/NOTES.md +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/README.md +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/__about__.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/__init__.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/cache.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/client.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/events.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/exceptions.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/models/__init__.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/py.typed +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/types.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/utilities/__init__.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/utilities/fs.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api/utilities/shared.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api.egg-info/SOURCES.txt +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api.egg-info/dependency_links.txt +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api.egg-info/requires.txt +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/mreg_api.egg-info/top_level.txt +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/pyproject.toml +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/setup.cfg +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/__init__.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/conftest.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/models/__init__.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/models/test_fields.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/models/test_history.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/models/test_models.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/test_cache.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/test_client.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/test_events.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/test_exceptions.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/tests/test_types.py +0 -0
- {mreg_api-0.2.0 → mreg_api-0.2.2}/uv.lock +0 -0
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
<!-- ## Unreleased -->
|
|
9
9
|
|
|
10
|
+
## [0.2.2](https://github.com/unioslo/mreg-api/releases/tag/0.2.2) - 2026-04-23
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Removed nullability of `NAPTR` fields.
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
|
|
18
|
+
- Duplicate endpoint `Endpoints.NAPTRs`. Now only `Endpoints.Naptrs` exists.
|
|
19
|
+
|
|
20
|
+
## [0.2.1](https://github.com/unioslo/mreg-api/releases/tag/0.2.1) - 2026-04-20
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `APIMixin.endpoint_with_id` property for getting the endpoint for the object with its ID, used for operations on the object itself (PATCH, DELETE, etc.). Used by default in `APIMixin.patch()` and `APIMixin.delete()`. Subclasses can override `endpoint_with_id` to provide custom endpoint resolution for these operations.
|
|
25
|
+
|
|
26
|
+
### Removed
|
|
27
|
+
|
|
28
|
+
- `Community.patch()`. Now uses `APIMixin.patch()`.
|
|
29
|
+
- `Community.delete()`. Now uses `APIMixin.delete()`.
|
|
30
|
+
- `APIMixin.patch()` response validation.
|
|
31
|
+
|
|
32
|
+
### Deprecated
|
|
33
|
+
|
|
34
|
+
- `APIMixin.patch()` parameter `validate`. Will be removed in 0.3.0.
|
|
35
|
+
|
|
10
36
|
## [0.2.0](https://github.com/unioslo/mreg-api/releases/tag/0.2.0) - 2026-04-16
|
|
11
37
|
|
|
12
38
|
### Added
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
21
|
+
__version__ = version = '0.2.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'ge065b8b90'
|
|
@@ -4,110 +4,25 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from abc import ABC
|
|
6
6
|
from abc import abstractmethod
|
|
7
|
-
from collections.abc import Mapping
|
|
8
7
|
from datetime import datetime
|
|
9
8
|
from typing import Any
|
|
10
|
-
from typing import Callable
|
|
11
9
|
from typing import Self
|
|
12
|
-
from typing import
|
|
10
|
+
from typing import overload
|
|
13
11
|
|
|
14
|
-
from pydantic import AliasChoices
|
|
15
12
|
from pydantic import BaseModel
|
|
16
13
|
from pydantic import ConfigDict
|
|
17
|
-
from
|
|
14
|
+
from typing_extensions import deprecated
|
|
18
15
|
|
|
19
16
|
from mreg_api.endpoints import Endpoint
|
|
20
17
|
from mreg_api.exceptions import EntityAlreadyExists
|
|
21
18
|
from mreg_api.exceptions import EntityNotFound
|
|
22
19
|
from mreg_api.exceptions import GetError
|
|
23
20
|
from mreg_api.exceptions import InternalError
|
|
24
|
-
from mreg_api.exceptions import PatchError
|
|
25
21
|
from mreg_api.exceptions import PostError
|
|
26
22
|
from mreg_api.types import JsonMapping
|
|
27
23
|
from mreg_api.types import QueryParams
|
|
28
24
|
|
|
29
25
|
|
|
30
|
-
def get_field_aliases(field_info: FieldInfo) -> set[str]:
|
|
31
|
-
"""Get all aliases for a Pydantic field."""
|
|
32
|
-
aliases: set[str] = set()
|
|
33
|
-
|
|
34
|
-
if field_info.alias:
|
|
35
|
-
aliases.add(field_info.alias)
|
|
36
|
-
|
|
37
|
-
if field_info.validation_alias:
|
|
38
|
-
if isinstance(field_info.validation_alias, str):
|
|
39
|
-
aliases.add(field_info.validation_alias)
|
|
40
|
-
elif isinstance(field_info.validation_alias, AliasChoices):
|
|
41
|
-
for choice in field_info.validation_alias.choices:
|
|
42
|
-
if isinstance(choice, str):
|
|
43
|
-
aliases.add(choice)
|
|
44
|
-
return aliases
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def get_model_aliases(model: BaseModel) -> dict[str, str]:
|
|
48
|
-
"""Get a mapping of aliases to field names for a Pydantic model.
|
|
49
|
-
|
|
50
|
-
Includes field names, alias, and validation alias(es).
|
|
51
|
-
"""
|
|
52
|
-
fields: dict[str, str] = {}
|
|
53
|
-
for field_name, field_info in model.model_fields.items():
|
|
54
|
-
aliases = get_field_aliases(field_info)
|
|
55
|
-
if model.model_config.get("populate_by_name"):
|
|
56
|
-
aliases.add(field_name)
|
|
57
|
-
# Assign aliases to field name in mapping
|
|
58
|
-
for alias in aliases:
|
|
59
|
-
fields[alias] = field_name
|
|
60
|
-
return fields
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def validate_patched_model(model: BaseModel, fields: Mapping[str, Any]) -> None:
|
|
64
|
-
"""Validate that model fields were patched correctly."""
|
|
65
|
-
aliases = get_model_aliases(model)
|
|
66
|
-
|
|
67
|
-
validators: dict[type, Callable[[Any, Any], bool]] = {
|
|
68
|
-
list: _validate_lists,
|
|
69
|
-
dict: _validate_dicts,
|
|
70
|
-
}
|
|
71
|
-
for key, value in fields.items():
|
|
72
|
-
field_name = key
|
|
73
|
-
if key in aliases:
|
|
74
|
-
field_name = aliases[key]
|
|
75
|
-
|
|
76
|
-
try:
|
|
77
|
-
nval = getattr(model, field_name)
|
|
78
|
-
except AttributeError as e:
|
|
79
|
-
raise PatchError(f"Could not get value for {field_name} in patched object.") from e
|
|
80
|
-
|
|
81
|
-
# Ensure patched value is the one we tried to set
|
|
82
|
-
validator = validators.get(
|
|
83
|
-
type(nval), # pyright:ignore[reportUnknownArgumentType, reportAny] # dict.get call with unknown type (Any) is fine
|
|
84
|
-
_validate_default,
|
|
85
|
-
)
|
|
86
|
-
if not validator(nval, value):
|
|
87
|
-
raise PatchError(
|
|
88
|
-
f"Patch failure! Tried to set {key} to {value!r}, but server returned {nval!r}."
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _validate_lists(new: list[Any], old: list[Any]) -> bool:
|
|
93
|
-
"""Validate that two lists are equal."""
|
|
94
|
-
if len(new) != len(old):
|
|
95
|
-
return False
|
|
96
|
-
return all(x in old for x in new)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def _validate_dicts(new: dict[str, Any], old: dict[str, Any]) -> bool:
|
|
100
|
-
"""Validate that two dictionaries are equal."""
|
|
101
|
-
if len(new) != len(old):
|
|
102
|
-
return False
|
|
103
|
-
return all(old.get(k) == v for k, v in new.items())
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _validate_default(new: Any, old: Any) -> bool:
|
|
107
|
-
"""Validate that two values are equal."""
|
|
108
|
-
return str(new) == str(old)
|
|
109
|
-
|
|
110
|
-
|
|
111
26
|
class FrozenModel(BaseModel):
|
|
112
27
|
"""Model for an immutable object."""
|
|
113
28
|
|
|
@@ -153,9 +68,17 @@ class APIMixin(ABC):
|
|
|
153
68
|
@classmethod
|
|
154
69
|
@abstractmethod
|
|
155
70
|
def endpoint(cls) -> Endpoint:
|
|
156
|
-
"""Return the endpoint for the
|
|
71
|
+
"""Return the endpoint for the resource."""
|
|
157
72
|
raise NotImplementedError("You must define an endpoint.")
|
|
158
73
|
|
|
74
|
+
@property
|
|
75
|
+
def endpoint_with_id(self) -> str:
|
|
76
|
+
"""Return the endpoint for the object with its ID.
|
|
77
|
+
|
|
78
|
+
Used for operations on the object itself (PATCH, DELETE, etc.).
|
|
79
|
+
"""
|
|
80
|
+
return self.endpoint().with_id(self.id_for_endpoint())
|
|
81
|
+
|
|
159
82
|
@classmethod
|
|
160
83
|
def get(cls, _id: int) -> Self | None:
|
|
161
84
|
"""Get an object.
|
|
@@ -526,8 +449,33 @@ class APIMixin(ABC):
|
|
|
526
449
|
raise GetError(f"Could not refresh {self.__class__.__name__} with ID {identifier}.")
|
|
527
450
|
return obj
|
|
528
451
|
|
|
452
|
+
@overload
|
|
453
|
+
@deprecated(
|
|
454
|
+
"APIMixin.patch() parameter 'validate' is deprecated and will be removed in a future version."
|
|
455
|
+
)
|
|
456
|
+
def patch(
|
|
457
|
+
self,
|
|
458
|
+
data: JsonMapping,
|
|
459
|
+
*,
|
|
460
|
+
params: QueryParams | None = None,
|
|
461
|
+
validate: bool,
|
|
462
|
+
) -> Self: ...
|
|
463
|
+
|
|
464
|
+
@overload
|
|
465
|
+
def patch(
|
|
466
|
+
self,
|
|
467
|
+
data: JsonMapping,
|
|
468
|
+
*,
|
|
469
|
+
params: QueryParams | None = ...,
|
|
470
|
+
validate: None = ...,
|
|
471
|
+
) -> Self: ...
|
|
472
|
+
|
|
529
473
|
def patch(
|
|
530
|
-
self,
|
|
474
|
+
self,
|
|
475
|
+
data: JsonMapping,
|
|
476
|
+
*,
|
|
477
|
+
params: QueryParams | None = None,
|
|
478
|
+
validate: bool | None = None, # noqa: ARG002 # pyright: ignore[reportUnusedParameter]
|
|
531
479
|
) -> Self:
|
|
532
480
|
"""Patch the object with the given values.
|
|
533
481
|
|
|
@@ -539,21 +487,16 @@ class APIMixin(ABC):
|
|
|
539
487
|
Args:
|
|
540
488
|
data: The values to patch.
|
|
541
489
|
params: Optional query parameters.
|
|
542
|
-
validate: Whether to validate the
|
|
490
|
+
validate: Whether to validate the response. (Deprecated and ignored)
|
|
543
491
|
|
|
544
492
|
Returns:
|
|
545
493
|
The object refetched from the server.
|
|
546
494
|
"""
|
|
547
495
|
from mreg_api.client import MregClient # noqa: PLC0415
|
|
548
496
|
|
|
549
|
-
MregClient().patch(self.
|
|
497
|
+
MregClient().patch(self.endpoint_with_id, json=data, params=params)
|
|
550
498
|
new_object = self.refetch()
|
|
551
499
|
|
|
552
|
-
if validate:
|
|
553
|
-
# __init_subclass__ guarantees we inherit from BaseModel
|
|
554
|
-
# but we can't signal this to the type checker, so we cast here.
|
|
555
|
-
validate_patched_model(cast(BaseModel, new_object), data) # pyright: ignore[reportInvalidCast] # we know what we are doing here (...?!)
|
|
556
|
-
|
|
557
500
|
return new_object
|
|
558
501
|
|
|
559
502
|
def delete(self) -> bool:
|
|
@@ -564,7 +507,7 @@ class APIMixin(ABC):
|
|
|
564
507
|
"""
|
|
565
508
|
from mreg_api.client import MregClient # noqa: PLC0415
|
|
566
509
|
|
|
567
|
-
response = MregClient().delete(self.
|
|
510
|
+
response = MregClient().delete(self.endpoint_with_id)
|
|
568
511
|
|
|
569
512
|
if response and response.is_success:
|
|
570
513
|
return True
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Custom field types for Pydantic models.
|
|
2
2
|
|
|
3
|
-
The types
|
|
3
|
+
The types resolve to basic types like str, int, etc., but with additional
|
|
4
4
|
validation added to them. The types are used in Pydantic models for consistent
|
|
5
5
|
validation of common fields such as hostnames, MAC addresses, etc.
|
|
6
6
|
|
|
@@ -14,6 +14,7 @@ from pydantic import field_validator
|
|
|
14
14
|
|
|
15
15
|
from mreg_api.endpoints import Endpoint
|
|
16
16
|
from mreg_api.exceptions import EntityNotFound
|
|
17
|
+
from mreg_api.types import JsonMapping
|
|
17
18
|
from mreg_api.types import QueryParams
|
|
18
19
|
from mreg_api.types import parse_json_mapping_string
|
|
19
20
|
|
|
@@ -62,7 +63,7 @@ class HistoryItem(BaseModel):
|
|
|
62
63
|
mid: int = Field(alias="model_id") # model_ is an internal pydantic namespace.
|
|
63
64
|
model: str
|
|
64
65
|
action: str
|
|
65
|
-
data:
|
|
66
|
+
data: JsonMapping
|
|
66
67
|
|
|
67
68
|
@field_validator("data", mode="before")
|
|
68
69
|
def parse_json_data(cls, v: Any) -> Any:
|
|
@@ -891,7 +891,7 @@ class Zone(FrozenModelWithTimestamps, WithTTL, APIMixin):
|
|
|
891
891
|
|
|
892
892
|
self.ensure_delegation_in_zone(name)
|
|
893
893
|
cls = Delegation.type_by_zone(self)
|
|
894
|
-
resp = MregClient().get(cls.
|
|
894
|
+
resp = MregClient().get(cls.endpoint_with_name(self, name), ok404=True)
|
|
895
895
|
if not resp:
|
|
896
896
|
return None
|
|
897
897
|
return cls.model_validate_json(resp.text)
|
|
@@ -951,7 +951,7 @@ class Zone(FrozenModelWithTimestamps, WithTTL, APIMixin):
|
|
|
951
951
|
# Check if delegation exists
|
|
952
952
|
self.ensure_delegation_in_zone(name) # check name
|
|
953
953
|
delegation = self.get_delegation_or_raise(name)
|
|
954
|
-
resp = MregClient().delete(delegation.
|
|
954
|
+
resp = MregClient().delete(delegation.endpoint_with_name(self, name))
|
|
955
955
|
return resp.is_success if resp else False
|
|
956
956
|
|
|
957
957
|
def set_delegation_comment(self, name: str, comment: str) -> None:
|
|
@@ -966,7 +966,7 @@ class Zone(FrozenModelWithTimestamps, WithTTL, APIMixin):
|
|
|
966
966
|
delegation = self.get_delegation_or_raise(name)
|
|
967
967
|
try:
|
|
968
968
|
MregClient().patch(
|
|
969
|
-
delegation.
|
|
969
|
+
delegation.endpoint_with_name(self, delegation.name), json={"comment": comment}
|
|
970
970
|
)
|
|
971
971
|
except PatchError as e:
|
|
972
972
|
# TODO: implement after mreg-cli parity
|
|
@@ -1087,7 +1087,7 @@ class Delegation(FrozenModelWithTimestamps, WithZone):
|
|
|
1087
1087
|
return Endpoint.ForwardZonesDelegations
|
|
1088
1088
|
|
|
1089
1089
|
@classmethod
|
|
1090
|
-
def
|
|
1090
|
+
def endpoint_with_name(cls, zone: Zone, name: str) -> str:
|
|
1091
1091
|
"""Return the path to a delegation in a specific zone."""
|
|
1092
1092
|
if cls.is_reverse():
|
|
1093
1093
|
endpoint = Endpoint.ReverseZonesDelegationsZone
|
|
@@ -2000,7 +2000,7 @@ class Network(FrozenModelWithTimestamps, APIMixin):
|
|
|
2000
2000
|
Returns:
|
|
2001
2001
|
The updated Network object.
|
|
2002
2002
|
"""
|
|
2003
|
-
return self.patch({"policy": policy.id}
|
|
2003
|
+
return self.patch({"policy": policy.id})
|
|
2004
2004
|
|
|
2005
2005
|
def set_max_communities(self, max_communities: int) -> Self:
|
|
2006
2006
|
"""Set the maximum number of communities for the network.
|
|
@@ -2011,7 +2011,7 @@ class Network(FrozenModelWithTimestamps, APIMixin):
|
|
|
2011
2011
|
Returns:
|
|
2012
2012
|
The updated Network object.
|
|
2013
2013
|
"""
|
|
2014
|
-
return self.patch({"max_communities": max_communities}
|
|
2014
|
+
return self.patch({"max_communities": max_communities})
|
|
2015
2015
|
|
|
2016
2016
|
def unset_policy(self) -> Self:
|
|
2017
2017
|
"""Unset the network policy of the network.
|
|
@@ -2019,7 +2019,7 @@ class Network(FrozenModelWithTimestamps, APIMixin):
|
|
|
2019
2019
|
Returns:
|
|
2020
2020
|
The updated Network object.
|
|
2021
2021
|
"""
|
|
2022
|
-
return self.patch({"policy": None}
|
|
2022
|
+
return self.patch({"policy": None})
|
|
2023
2023
|
|
|
2024
2024
|
def unset_max_communities(self) -> Self:
|
|
2025
2025
|
"""Unset the maximum number of communities for the network.
|
|
@@ -2027,7 +2027,7 @@ class Network(FrozenModelWithTimestamps, APIMixin):
|
|
|
2027
2027
|
Returns:
|
|
2028
2028
|
The updated Network object.
|
|
2029
2029
|
"""
|
|
2030
|
-
return self.patch({"max_communities": None}
|
|
2030
|
+
return self.patch({"max_communities": None})
|
|
2031
2031
|
|
|
2032
2032
|
|
|
2033
2033
|
class NetworkPolicyAttribute(FrozenModelWithTimestamps, WithName):
|
|
@@ -2068,6 +2068,7 @@ class Community(FrozenModelWithTimestamps, APIMixin):
|
|
|
2068
2068
|
return Endpoint.NetworkCommunity
|
|
2069
2069
|
|
|
2070
2070
|
@property
|
|
2071
|
+
@override
|
|
2071
2072
|
def endpoint_with_id(self) -> str:
|
|
2072
2073
|
"""Return the endpoint with the community ID."""
|
|
2073
2074
|
return self.endpoint().with_params(self.network_address, self.id)
|
|
@@ -2088,42 +2089,6 @@ class Community(FrozenModelWithTimestamps, APIMixin):
|
|
|
2088
2089
|
|
|
2089
2090
|
return MregClient().get_typed(self.endpoint_with_id, self.__class__)
|
|
2090
2091
|
|
|
2091
|
-
@override
|
|
2092
|
-
def patch(
|
|
2093
|
-
self,
|
|
2094
|
-
data: JsonMapping,
|
|
2095
|
-
*,
|
|
2096
|
-
params: QueryParams | None = None,
|
|
2097
|
-
validate: bool = False, # noqa: ARG002, E501
|
|
2098
|
-
) -> Self:
|
|
2099
|
-
"""Patch the community.
|
|
2100
|
-
|
|
2101
|
-
Args:
|
|
2102
|
-
data: The data to patch.
|
|
2103
|
-
params: Optional query parameters.
|
|
2104
|
-
validate: Whether to validate the response. (Not implemented)
|
|
2105
|
-
|
|
2106
|
-
Returns:
|
|
2107
|
-
The updated Community object.
|
|
2108
|
-
"""
|
|
2109
|
-
from mreg_api.client import MregClient # noqa: PLC0415
|
|
2110
|
-
|
|
2111
|
-
try:
|
|
2112
|
-
MregClient().patch(self.endpoint_with_id, json=data, params=params)
|
|
2113
|
-
except PatchError as e:
|
|
2114
|
-
# TODO: implement after mreg-cli parity
|
|
2115
|
-
# raise PatchError(f"Failed to patch community {self.name!r}", e.response) from e
|
|
2116
|
-
raise e
|
|
2117
|
-
new_object = self.refetch()
|
|
2118
|
-
return new_object
|
|
2119
|
-
|
|
2120
|
-
def delete(self) -> bool:
|
|
2121
|
-
"""Delete the community."""
|
|
2122
|
-
from mreg_api.client import MregClient # noqa: PLC0415
|
|
2123
|
-
|
|
2124
|
-
resp = MregClient().delete(self.endpoint_with_id)
|
|
2125
|
-
return resp.is_success if resp else False
|
|
2126
|
-
|
|
2127
2092
|
def get_hosts(self) -> list[Host]:
|
|
2128
2093
|
"""Get a list of hosts in the community.
|
|
2129
2094
|
|
|
@@ -2286,7 +2251,6 @@ class NetworkPolicy(FrozenModelWithTimestamps, WithName):
|
|
|
2286
2251
|
"""
|
|
2287
2252
|
self.patch(
|
|
2288
2253
|
{"attributes": [{"name": a.name, "value": a.value} for a in attrs]},
|
|
2289
|
-
validate=False,
|
|
2290
2254
|
)
|
|
2291
2255
|
# NOTE: can return self.refetch() here if we need to refresh the object
|
|
2292
2256
|
|
|
@@ -2468,7 +2432,7 @@ class IPAddress(FrozenModelWithTimestamps, WithHost, APIMixin):
|
|
|
2468
2432
|
A new IPAddress object fetched from the API with the MAC address removed.
|
|
2469
2433
|
"""
|
|
2470
2434
|
# Model converts empty string to None so we must validate this ourselves.
|
|
2471
|
-
patched = self.patch(data={"macaddress": ""}
|
|
2435
|
+
patched = self.patch(data={"macaddress": ""})
|
|
2472
2436
|
if patched.macaddress:
|
|
2473
2437
|
raise PatchError(f"Failed to disassociate MAC address from {self.ipaddress}")
|
|
2474
2438
|
return patched
|
|
@@ -2639,9 +2603,9 @@ class NAPTR(FrozenModelWithTimestamps, WithHost, APIMixin):
|
|
|
2639
2603
|
id: int # noqa: A003
|
|
2640
2604
|
preference: int
|
|
2641
2605
|
order: int
|
|
2642
|
-
flag: str
|
|
2643
|
-
service: str
|
|
2644
|
-
regex: str
|
|
2606
|
+
flag: str
|
|
2607
|
+
service: str
|
|
2608
|
+
regex: str
|
|
2645
2609
|
replacement: str
|
|
2646
2610
|
|
|
2647
2611
|
@classmethod
|
|
@@ -2650,7 +2614,7 @@ class NAPTR(FrozenModelWithTimestamps, WithHost, APIMixin):
|
|
|
2650
2614
|
return Endpoint.Naptrs
|
|
2651
2615
|
|
|
2652
2616
|
@classmethod
|
|
2653
|
-
def headers(cls) -> list[str]:
|
|
2617
|
+
def headers(cls) -> list[str]: # TODO: remove. Move to mreg-cli
|
|
2654
2618
|
"""Return the headers for the NAPTR record."""
|
|
2655
2619
|
return [
|
|
2656
2620
|
"NAPTRs:",
|
|
@@ -3282,7 +3246,7 @@ class Host(FrozenModelWithTimestamps, WithTTL, WithHistory, APIMixin):
|
|
|
3282
3246
|
Host: Updated Host object.
|
|
3283
3247
|
"""
|
|
3284
3248
|
# Uses non-atomic host update via PATCH to set the contacts list.
|
|
3285
|
-
return self.patch(data={"contacts": contacts}
|
|
3249
|
+
return self.patch(data={"contacts": contacts})
|
|
3286
3250
|
|
|
3287
3251
|
def add_contacts(self, contacts: list[str]) -> HostContactModification:
|
|
3288
3252
|
"""Add contacts to the host.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|