Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .changes/unreleased/optimization-20260617-052412.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: optimization
body: Adds validation for backup retention days on SQL DB
time: 2026-06-17T05:24:12.568818136Z
custom:
Author: v-alexmoraru
AuthorLink: https://github.com/v-alexmoraru
10 changes: 9 additions & 1 deletion src/fabric_cli/commands/fs/set/fab_fs_set_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
from fabric_cli.core import fab_constant
from fabric_cli.core.fab_commands import Command
from fabric_cli.core.fab_exceptions import FabricCLIError
from fabric_cli.core.fab_types import definition_format_mapping, format_mapping
from fabric_cli.core.fab_types import (
ItemType,
definition_format_mapping,
format_mapping,
)
from fabric_cli.core.hiearchy.fab_hiearchy import Item
from fabric_cli.errors.common import CommonErrors
from fabric_cli.utils import fab_cmd_set_utils as utils_set
Expand All @@ -24,6 +28,10 @@ def exec(item: Item, args: Namespace) -> None:

utils_set.validate_item_query(query_value, item)

# Validate SQLDatabase-specific properties
if item.item_type == ItemType.SQL_DATABASE:
utils_set.validate_sql_database_property(query_value, args.input)

utils_set.print_set_warning()
if force or utils_ui.prompt_confirm():
args.output = None
Expand Down
6 changes: 6 additions & 0 deletions src/fabric_cli/core/fab_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,9 @@
# Invalid query parameters for set command across all fabric resources
SET_COMMAND_INVALID_QUERIES = ["id", "type", "workspaceId", "folderId"]

# SQLDatabase property validation
SQL_DATABASE_BACKUP_RETENTION = {
"property": "properties.backupRetentionDays",
"min_days": 1,
"max_days": 35,
}
Comment on lines +356 to +360

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in second thought, i dont think we need to maintain it in here and only define it in the set utils file.

7 changes: 7 additions & 0 deletions src/fabric_cli/errors/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,10 @@ def unsupported_parameter(key: str) -> str:
@staticmethod
def invalid_parameter_format(param: str) -> str:
return f"Invalid parameter format: '{param}'. Use key=value or key!=value."

@staticmethod
def invalid_backup_retention_days(value: str, min_days: int, max_days: int) -> str:
return (
f"Invalid backup retention days value '{value}'. "
f"Must be an integer between {min_days} and {max_days} days."
)
42 changes: 42 additions & 0 deletions src/fabric_cli/utils/fab_cmd_set_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,48 @@ def validate_query_not_in_blocklist(
)


def validate_sql_database_property(query: str, input_value: str) -> None:
"""Validate SQLDatabase-specific property values.

Args:
query: The property query path being set.
input_value: The input value to validate.

Raises:
FabricCLIError: If the value is invalid for the property.
"""
if query == fab_constant.SQL_DATABASE_BACKUP_RETENTION["property"]:
min_days: int = fab_constant.SQL_DATABASE_BACKUP_RETENTION["min_days"] # type: ignore[assignment]
max_days: int = fab_constant.SQL_DATABASE_BACKUP_RETENTION["max_days"] # type: ignore[assignment]
Comment thread
v-alexmoraru marked this conversation as resolved.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it is a bit of overkill, lets simplify

Suggested change
max_days: int = fab_constant.SQL_DATABASE_BACKUP_RETENTION["max_days"] # type: ignore[assignment]
if query == "properties.backupRetentionDays":
try:
value = int(input_value)
except (TypeError, ValueError):
value = None
if value is None or not (fab_constant.SQL_DATABASE_BACKUP_RETENTION_MIN_DAYS <= value <= fab_constant.SQL_DATABASE_BACKUP_RETENTION_MAX_DAYS):
raise FabricCLIError(
CommonErrors.invalid_backup_retention_days(
input_value, min_days, max_days
),
fab_constant.ERROR_INVALID_INPUT,
)


try:
try:
value = int(input_value)
except ValueError:
# Fall back to JSON for encoded values like '7' or '"7"'
parsed = json.loads(input_value)
Comment thread
v-alexmoraru marked this conversation as resolved.
if type(parsed) is int:
value = parsed
elif isinstance(parsed, str):
value = int(parsed)
Comment thread
v-alexmoraru marked this conversation as resolved.
else:
raise ValueError("Value must be an integer")

# Validate range
if not min_days <= value <= max_days:
raise ValueError("Out of range")

except (ValueError, TypeError, json.JSONDecodeError):
raise FabricCLIError(
CommonErrors.invalid_backup_retention_days(
str(input_value),
min_days,
max_days,
),
fab_constant.ERROR_INVALID_INPUT,
)
Comment thread
v-alexmoraru marked this conversation as resolved.


def ensure_notebook_dependency(decoded_item_def: dict, query: str) -> dict:
dependency_types = ["lakehouse", "warehouse", "environment"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (None; Darwin/25.5.0; Python/3.12.13)
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
Expand All @@ -26,15 +26,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '2561'
- '3271'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:06 GMT
- Mon, 22 Jun 2026 10:24:15 GMT
Pragma:
- no-cache
RequestId:
- 93630144-c10b-421b-9f61-b4c9e96e53ce
- 0ac62403-a6a3-4d41-9ba3-003c8602aba5
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand All @@ -60,7 +60,7 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (None; Darwin/25.5.0; Python/3.12.13)
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
Expand All @@ -75,15 +75,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '2561'
- '3271'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:08 GMT
- Mon, 22 Jun 2026 10:24:16 GMT
Pragma:
- no-cache
RequestId:
- 222a5ebf-a440-4c9b-8a2c-0e1e46b6b6ba
- 99ad22cd-a211-49c1-a265-65387ef2f3a8
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand All @@ -109,7 +109,7 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (None; Darwin/25.5.0; Python/3.12.13)
method: GET
uri: https://api.fabric.microsoft.com/v1/capacities
response:
Expand All @@ -125,15 +125,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '426'
- '467'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:13 GMT
- Mon, 22 Jun 2026 10:24:20 GMT
Pragma:
- no-cache
RequestId:
- dfb69fa0-b455-4808-ae5f-1a7ddef6e34b
- 4125973b-3677-4f49-b023-d3d1c7e54013
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand Down Expand Up @@ -162,13 +162,14 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (None; Darwin/25.5.0; Python/3.12.13)
method: POST
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
body:
string: '{"id": "81517fa4-30e3-42e6-b751-b36af1c8e99a", "displayName": "fabriccli_WorkspacePerTestclass_000001",
"description": "", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}'
string: '{"id": "01b1815a-ce26-4272-b8b1-5bb469afc785", "displayName": "fabriccli_WorkspacePerTestclass_000001",
"description": "", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004",
"capacityRegion": "Central US"}'
headers:
Access-Control-Expose-Headers:
- RequestId,Location
Expand All @@ -177,17 +178,17 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '175'
- '196'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:21 GMT
- Mon, 22 Jun 2026 10:24:27 GMT
Location:
- https://api.fabric.microsoft.com/v1/workspaces/81517fa4-30e3-42e6-b751-b36af1c8e99a
- https://api.fabric.microsoft.com/v1/workspaces/01b1815a-ce26-4272-b8b1-5bb469afc785
Pragma:
- no-cache
RequestId:
- 6f6fd3f9-2eeb-4e85-afe0-f530855a0a0f
- 7e828071-8289-4077-8d4d-e3457f16519e
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand All @@ -213,15 +214,16 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (set; Darwin/25.5.0; Python/3.12.13)
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
body:
string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName":
"My workspace", "description": "", "type": "Personal"}, {"id": "81517fa4-30e3-42e6-b751-b36af1c8e99a",
"My workspace", "description": "", "type": "Personal"}, {"id": "01b1815a-ce26-4272-b8b1-5bb469afc785",
"displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "",
"type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}'
"type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004",
"capacityRegion": "Central US"}]}'
headers:
Access-Control-Expose-Headers:
- RequestId
Expand All @@ -230,15 +232,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '2595'
- '3305'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:33 GMT
- Mon, 22 Jun 2026 10:27:17 GMT
Pragma:
- no-cache
RequestId:
- 5a815f03-74e2-4496-aae0-2364a02687cd
- 9e78df05-b2a2-4ce4-843a-bda0398b43cf
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand All @@ -264,9 +266,9 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (set; Darwin/25.5.0; Python/3.12.13)
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces/81517fa4-30e3-42e6-b751-b36af1c8e99a/items
uri: https://api.fabric.microsoft.com/v1/workspaces/01b1815a-ce26-4272-b8b1-5bb469afc785/items
response:
body:
string: '{"value": []}'
Expand All @@ -282,11 +284,11 @@ interactions:
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:34 GMT
- Mon, 22 Jun 2026 10:27:17 GMT
Pragma:
- no-cache
RequestId:
- 1283e8eb-846f-49ab-b1e4-4438ef0df0f9
- 6c9a0dc2-a403-4a19-b791-a85c6e9f0901
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand Down Expand Up @@ -314,9 +316,9 @@ interactions:
Content-Type:
- application/json
User-Agent:
- ms-fabric-cli/1.6.1 (set; Darwin/25.4.0; Python/3.12.13)
- ms-fabric-cli/1.6.1 (set; Darwin/25.5.0; Python/3.12.13)
method: DELETE
uri: https://api.fabric.microsoft.com/v1/workspaces/81517fa4-30e3-42e6-b751-b36af1c8e99a
uri: https://api.fabric.microsoft.com/v1/workspaces/01b1815a-ce26-4272-b8b1-5bb469afc785
response:
body:
string: ''
Expand All @@ -332,11 +334,11 @@ interactions:
Content-Type:
- application/octet-stream
Date:
- Wed, 13 May 2026 11:03:35 GMT
- Mon, 22 Jun 2026 10:27:18 GMT
Pragma:
- no-cache
RequestId:
- b0ec7a9f-0f36-4321-9c58-823c5894cd4c
- 216a3d44-a475-48ff-88a9-7edcfacbac44
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand Down
Loading
Loading