diff --git a/CHANGELOG.md b/CHANGELOG.md index 534f6663c..6678a96b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,19 @@ ## Release (2026-MM-DD) -- `sfs`: [v0.4.0](services/sfs/CHANGELOG.md#v040) - - **Feature:** model `CreateResourcePoolPayload` now has an additional field `snapshotPolicyId` - - **Feature:** model `CreateResourcePoolSnapshotPayload` now has an additional field `snaplockRetentionHours` - - **Feature:** model `ResourcePool` now has an additional field `snapshotPolicy` - - **Feature:** model `ResourcePoolSnapshot` now has an additional field `snaplockExpiryTime` - - **Feature:** model `ResourcePoolSpace` now has an additional field `usedBySnapshotsGigabytes` - - **Feature:** model `UpdateResourcePoolPayload` now has an additional field `snapshotPolicyId` - - **Feature:** new models: `DisableLockResponse`, `EnableLockResponse`, `GetLockResponse`, `GetScheduleResponse`, `GetSnapshotPolicyResponse`, `ListSchedulesResponse`, `ListSnapshotPoliciesResponse`, `ResourcePoolSnapshotPolicy`, `Schedule`, `SnapshotPolicy`, `SnapshotPolicySchedule`, `UpdateResourcePoolSnapshotPayload`, `UpdateResourcePoolSnapshotResponse` - - **Feature:** new operations: `UpdateResourcePoolSnapshot`, `ListSchedules`, `GetSchedule`, `ListSnapshotPolicies`, `GetSnapshotPolicy`, `DisableLock`, `GetLock`, `EnableLock`, +- `sfs`: + - [v0.5.0](services/sfs/CHANGELOG.md#v050) + - **Deprecation:** deprecated field `schedules` in model `SnapshotPolicy` + - **Feature:** new field `snapshotSchedules` in model `SnapshotPolicy` + - **Feature:** new field `interval` in model `SnapshotPolicySchedule` + - **Feature:** new model `SnapshotPolicySnapshotPolicySchedule` + - [v0.4.0](services/sfs/CHANGELOG.md#v040) + - **Feature:** model `CreateResourcePoolPayload` now has an additional field `snapshotPolicyId` + - **Feature:** model `CreateResourcePoolSnapshotPayload` now has an additional field `snaplockRetentionHours` + - **Feature:** model `ResourcePool` now has an additional field `snapshotPolicy` + - **Feature:** model `ResourcePoolSnapshot` now has an additional field `snaplockExpiryTime` + - **Feature:** model `ResourcePoolSpace` now has an additional field `usedBySnapshotsGigabytes` + - **Feature:** model `UpdateResourcePoolPayload` now has an additional field `snapshotPolicyId` + - **Feature:** new models: `DisableLockResponse`, `EnableLockResponse`, `GetLockResponse`, `GetScheduleResponse`, `GetSnapshotPolicyResponse`, `ListSchedulesResponse`, `ListSnapshotPoliciesResponse`, `ResourcePoolSnapshotPolicy`, `Schedule`, `SnapshotPolicy`, `SnapshotPolicySchedule`, `UpdateResourcePoolSnapshotPayload`, `UpdateResourcePoolSnapshotResponse` + - **Feature:** new operations: `UpdateResourcePoolSnapshot`, `ListSchedules`, `GetSchedule`, `ListSnapshotPolicies`, `GetSnapshotPolicy`, `DisableLock`, `GetLock`, `EnableLock`, - `ske`: [v1.8.0](services/ske/CHANGELOG.md#v180) - **Breaking Change:** Change status codes: remove 200, change response type of 202 and add 400 in some API calls - **Breaking Change:** Aligned CRI name validation with the API side validation (removed docker) diff --git a/services/sfs/CHANGELOG.md b/services/sfs/CHANGELOG.md index a79eba733..c972eb684 100644 --- a/services/sfs/CHANGELOG.md +++ b/services/sfs/CHANGELOG.md @@ -1,3 +1,9 @@ +## v0.5.0 +- **Deprecation:** deprecated field `schedules` in model `SnapshotPolicy` +- **Feature:** new field `snapshotSchedules` in model `SnapshotPolicy` +- **Feature:** new field `interval` in model `SnapshotPolicySchedule` +- **Feature:** new model `SnapshotPolicySnapshotPolicySchedule` + ## v0.4.0 - **Feature:** model `CreateResourcePoolPayload` now has an additional field `snapshotPolicyId` - **Feature:** model `CreateResourcePoolSnapshotPayload` now has an additional field `snaplockRetentionHours` diff --git a/services/sfs/oas_commit b/services/sfs/oas_commit index 4b79dc0b4..7d5fc0bc0 100644 --- a/services/sfs/oas_commit +++ b/services/sfs/oas_commit @@ -1 +1 @@ -bda6ad3d9e8850526f25eddcb6589fcc7559c625 +a896a71ffc1c1152f63b40a0194ac461ce179d6c diff --git a/services/sfs/pyproject.toml b/services/sfs/pyproject.toml index c8eb55a08..dfe19b900 100644 --- a/services/sfs/pyproject.toml +++ b/services/sfs/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "stackit-sfs" -version = "v0.4.0" +version = "v0.5.0" description = "STACKIT File Storage (SFS)" authors = [{ name = "STACKIT Developer Tools", email = "developer-tools@stackit.cloud" }] requires-python = ">=3.9,<4" diff --git a/services/sfs/src/stackit/sfs/__init__.py b/services/sfs/src/stackit/sfs/__init__.py index 9e5c2d55a..2b27b6957 100644 --- a/services/sfs/src/stackit/sfs/__init__.py +++ b/services/sfs/src/stackit/sfs/__init__.py @@ -66,6 +66,7 @@ "ShareExportPolicyRule", "SnapshotPolicy", "SnapshotPolicySchedule", + "SnapshotPolicySnapshotPolicySchedule", "Status", "UpdateResourcePoolPayload", "UpdateResourcePoolResponse", @@ -193,6 +194,9 @@ from stackit.sfs.models.snapshot_policy_schedule import ( SnapshotPolicySchedule as SnapshotPolicySchedule, ) +from stackit.sfs.models.snapshot_policy_snapshot_policy_schedule import ( + SnapshotPolicySnapshotPolicySchedule as SnapshotPolicySnapshotPolicySchedule, +) from stackit.sfs.models.status import Status as Status from stackit.sfs.models.update_resource_pool_payload import ( UpdateResourcePoolPayload as UpdateResourcePoolPayload, diff --git a/services/sfs/src/stackit/sfs/models/__init__.py b/services/sfs/src/stackit/sfs/models/__init__.py index 238a30c70..d08b82376 100644 --- a/services/sfs/src/stackit/sfs/models/__init__.py +++ b/services/sfs/src/stackit/sfs/models/__init__.py @@ -75,6 +75,9 @@ from stackit.sfs.models.share_export_policy_rule import ShareExportPolicyRule from stackit.sfs.models.snapshot_policy import SnapshotPolicy from stackit.sfs.models.snapshot_policy_schedule import SnapshotPolicySchedule +from stackit.sfs.models.snapshot_policy_snapshot_policy_schedule import ( + SnapshotPolicySnapshotPolicySchedule, +) from stackit.sfs.models.status import Status from stackit.sfs.models.update_resource_pool_payload import UpdateResourcePoolPayload from stackit.sfs.models.update_resource_pool_response import UpdateResourcePoolResponse diff --git a/services/sfs/src/stackit/sfs/models/snapshot_policy.py b/services/sfs/src/stackit/sfs/models/snapshot_policy.py index a73a9061e..6853d5f04 100644 --- a/services/sfs/src/stackit/sfs/models/snapshot_policy.py +++ b/services/sfs/src/stackit/sfs/models/snapshot_policy.py @@ -30,6 +30,9 @@ from typing_extensions import Self from stackit.sfs.models.snapshot_policy_schedule import SnapshotPolicySchedule +from stackit.sfs.models.snapshot_policy_snapshot_policy_schedule import ( + SnapshotPolicySnapshotPolicySchedule, +) class SnapshotPolicy(BaseModel): @@ -42,8 +45,21 @@ class SnapshotPolicy(BaseModel): enabled: Optional[StrictBool] = Field(default=None, description="Wether the Snapshot Policy is enabled") id: Optional[StrictStr] = Field(default=None, description="ID of the Snapshot Policy") name: Optional[StrictStr] = Field(default=None, description="Name of the Snapshot Policy") - schedules: Optional[List[SnapshotPolicySchedule]] = Field(default=None, description="associated schedules") - __properties: ClassVar[List[str]] = ["comment", "createdAt", "enabled", "id", "name", "schedules"] + schedules: Optional[List[SnapshotPolicySchedule]] = Field( + default=None, description="(deprecated) associated schedules" + ) + snapshot_schedules: Optional[List[SnapshotPolicySnapshotPolicySchedule]] = Field( + default=None, description="associated schedules", alias="snapshotSchedules" + ) + __properties: ClassVar[List[str]] = [ + "comment", + "createdAt", + "enabled", + "id", + "name", + "schedules", + "snapshotSchedules", + ] @field_validator("created_at", mode="before") def created_at_change_year_zero_to_one(cls, value): @@ -102,6 +118,13 @@ def to_dict(self) -> Dict[str, Any]: if _item_schedules: _items.append(_item_schedules.to_dict()) _dict["schedules"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in snapshot_schedules (list) + _items = [] + if self.snapshot_schedules: + for _item_snapshot_schedules in self.snapshot_schedules: + if _item_snapshot_schedules: + _items.append(_item_snapshot_schedules.to_dict()) + _dict["snapshotSchedules"] = _items return _dict @classmethod @@ -125,6 +148,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if obj.get("schedules") is not None else None ), + "snapshotSchedules": ( + [SnapshotPolicySnapshotPolicySchedule.from_dict(_item) for _item in obj["snapshotSchedules"]] + if obj.get("snapshotSchedules") is not None + else None + ), } ) return _obj diff --git a/services/sfs/src/stackit/sfs/models/snapshot_policy_schedule.py b/services/sfs/src/stackit/sfs/models/snapshot_policy_schedule.py index 675f2a6e8..0a4284066 100644 --- a/services/sfs/src/stackit/sfs/models/snapshot_policy_schedule.py +++ b/services/sfs/src/stackit/sfs/models/snapshot_policy_schedule.py @@ -26,11 +26,18 @@ class SnapshotPolicySchedule(BaseModel): SnapshotPolicySchedule """ # noqa: E501 - count: Optional[StrictInt] = None - prefix: Optional[StrictStr] = None - retention_period: Optional[StrictStr] = Field(default=None, alias="retentionPeriod") - schedule_id: Optional[StrictStr] = Field(default=None, alias="scheduleId") - __properties: ClassVar[List[str]] = ["count", "prefix", "retentionPeriod", "scheduleId"] + count: Optional[StrictInt] = Field(default=None, description="Retention Count") + interval: Optional[StrictStr] = Field( + default=None, description="Interval of the Schedule (follows the cron schedule expression in Unix-like systems)" + ) + prefix: Optional[StrictStr] = Field( + default=None, description="Prefix used for the snapshots created by this policy" + ) + retention_period: Optional[StrictStr] = Field( + default=None, description='Retention Period (ISO 8601 format or "infinite")', alias="retentionPeriod" + ) + schedule_id: Optional[StrictStr] = Field(default=None, description="ID of the Schedule", alias="scheduleId") + __properties: ClassVar[List[str]] = ["count", "interval", "prefix", "retentionPeriod", "scheduleId"] model_config = ConfigDict( populate_by_name=True, @@ -83,6 +90,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "count": obj.get("count"), + "interval": obj.get("interval"), "prefix": obj.get("prefix"), "retentionPeriod": obj.get("retentionPeriod"), "scheduleId": obj.get("scheduleId"), diff --git a/services/sfs/src/stackit/sfs/models/snapshot_policy_snapshot_policy_schedule.py b/services/sfs/src/stackit/sfs/models/snapshot_policy_snapshot_policy_schedule.py new file mode 100644 index 000000000..d4706545d --- /dev/null +++ b/services/sfs/src/stackit/sfs/models/snapshot_policy_snapshot_policy_schedule.py @@ -0,0 +1,126 @@ +# coding: utf-8 + +""" + STACKIT File Storage (SFS) + + API used to create and manage NFS Shares. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from datetime import datetime +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing_extensions import Self + + +class SnapshotPolicySnapshotPolicySchedule(BaseModel): + """ + SnapshotPolicySnapshotPolicySchedule + """ # noqa: E501 + + created_at: Optional[datetime] = Field(default=None, alias="createdAt") + id: Optional[StrictStr] = Field(default=None, description="ID of the Schedule") + interval: Optional[StrictStr] = Field( + default=None, description="Interval of the Schedule (follows the cron schedule expression in Unix-like systems)" + ) + name: Optional[StrictStr] = Field(default=None, description="Name of the Schedule") + prefix: Optional[StrictStr] = Field( + default=None, description="Prefix used for the snapshots created by this policy" + ) + retention_count: Optional[StrictInt] = Field(default=None, description="Retention Count", alias="retentionCount") + retention_period: Optional[StrictStr] = Field( + default=None, description='Retention Period (ISO 8601 format or "infinite")', alias="retentionPeriod" + ) + __properties: ClassVar[List[str]] = [ + "createdAt", + "id", + "interval", + "name", + "prefix", + "retentionCount", + "retentionPeriod", + ] + + @field_validator("created_at", mode="before") + def created_at_change_year_zero_to_one(cls, value): + """Workaround which prevents year 0 issue""" + if isinstance(value, str): + # Check for year "0000" at the beginning of the string + # This assumes common date formats like YYYY-MM-DDTHH:MM:SS+00:00 or YYYY-MM-DDTHH:MM:SSZ + if value.startswith("0000-01-01T") and re.match( + r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\+\d{2}:\d{2}|Z)$", value + ): + # Workaround: Replace "0000" with "0001" + return "0001" + value[4:] # Take "0001" and append the rest of the string + return value + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of SnapshotPolicySnapshotPolicySchedule from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SnapshotPolicySnapshotPolicySchedule from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "createdAt": obj.get("createdAt"), + "id": obj.get("id"), + "interval": obj.get("interval"), + "name": obj.get("name"), + "prefix": obj.get("prefix"), + "retentionCount": obj.get("retentionCount"), + "retentionPeriod": obj.get("retentionPeriod"), + } + ) + return _obj