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
4 changes: 4 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,7 @@
# 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_MIN_DAYS = 1
SQL_DATABASE_BACKUP_RETENTION_MAX_DAYS = 35
SQL_DATABASE_BACKUP_RETENTION_PROPERTY = "properties.backupRetentionDays"
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 backupRetentionDays value '{value}'. "
f"Must be an integer between {min_days} and {max_days} days."
)
50 changes: 48 additions & 2 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,50 @@ 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 = fab_constant.SQL_DATABASE_BACKUP_RETENTION_MIN_DAYS
max_days = fab_constant.SQL_DATABASE_BACKUP_RETENTION_MAX_DAYS

try:
try:
value = int(input_value)
except ValueError:
# Fall back to JSON for encoded values like '7' or '"7"'
parsed = json.loads(input_value)
if isinstance(parsed, bool):
raise ValueError("Booleans are not valid integer values")
elif isinstance(parsed, int):
value = parsed
elif isinstance(parsed, str):
value = int(parsed)
Comment on lines +113 to +120
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 on lines +95 to +136


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

Expand Down Expand Up @@ -194,7 +238,8 @@ def update_cache(


def print_set_warning() -> None:
fab_logger.log_warning("Modifying properties may lead to unintended consequences")
fab_logger.log_warning(
"Modifying properties may lead to unintended consequences")


def extract_updated_properties(updated_data: dict, query_path: str) -> dict:
Expand Down Expand Up @@ -260,7 +305,8 @@ def _decode_payload(item_def: dict) -> dict:
payload_base64 = part["payload"]

if payload_base64:
decoded_payload = base64.b64decode(payload_base64).decode("utf-8")
decoded_payload = base64.b64decode(
payload_base64).decode("utf-8")
decoded_payload = json.loads(decoded_payload)
# Store the decoded payload
part["payload"] = decoded_payload
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; Linux/6.12.76-linuxkit; Python/3.12.11)
Comment thread
v-alexmoraru marked this conversation as resolved.
Comment thread
v-alexmoraru marked this conversation as resolved.
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
Expand All @@ -26,15 +26,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '2561'
- '3227'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:06 GMT
- Tue, 16 Jun 2026 11:09:08 GMT
Pragma:
- no-cache
RequestId:
- 93630144-c10b-421b-9f61-b4c9e96e53ce
- 9b4bbf47-d81b-420e-8f29-be7f7022d3db
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; Linux/6.12.76-linuxkit; Python/3.12.11)
Comment thread
v-alexmoraru marked this conversation as resolved.
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
Expand All @@ -75,15 +75,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '2561'
- '3227'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:08 GMT
- Tue, 16 Jun 2026 11:09:09 GMT
Pragma:
- no-cache
RequestId:
- 222a5ebf-a440-4c9b-8a2c-0e1e46b6b6ba
- 7fa2ea2b-8df6-4d7d-806f-ffa179a9b2f7
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; Linux/6.12.76-linuxkit; Python/3.12.11)
Comment thread
v-alexmoraru marked this conversation as resolved.
method: GET
uri: https://api.fabric.microsoft.com/v1/capacities
response:
Expand All @@ -125,15 +125,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '426'
- '462'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:13 GMT
- Tue, 16 Jun 2026 11:09:14 GMT
Pragma:
- no-cache
RequestId:
- dfb69fa0-b455-4808-ae5f-1a7ddef6e34b
- 4aaf4ac5-968d-424b-b2fc-8d0b6cf85d77
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand Down Expand Up @@ -162,12 +162,12 @@ 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; Linux/6.12.76-linuxkit; Python/3.12.11)
method: POST
uri: https://api.fabric.microsoft.com/v1/workspaces
response:
body:
string: '{"id": "81517fa4-30e3-42e6-b751-b36af1c8e99a", "displayName": "fabriccli_WorkspacePerTestclass_000001",
string: '{"id": "fd1b2648-dbb2-442c-b4c7-73b02f7f8a2a", "displayName": "fabriccli_WorkspacePerTestclass_000001",
"description": "", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}'
headers:
Access-Control-Expose-Headers:
Expand All @@ -177,17 +177,17 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '175'
- '176'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:21 GMT
- Tue, 16 Jun 2026 11:09:20 GMT
Location:
- https://api.fabric.microsoft.com/v1/workspaces/81517fa4-30e3-42e6-b751-b36af1c8e99a
- https://api.fabric.microsoft.com/v1/workspaces/fd1b2648-dbb2-442c-b4c7-73b02f7f8a2a
Pragma:
- no-cache
RequestId:
- 6f6fd3f9-2eeb-4e85-afe0-f530855a0a0f
- 143453b7-f98d-4fe3-886b-fcdfbe94253d
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand All @@ -213,13 +213,13 @@ 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; Linux/6.12.76-linuxkit; Python/3.12.11)
Comment thread
v-alexmoraru marked this conversation as resolved.
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": "fd1b2648-dbb2-442c-b4c7-73b02f7f8a2a",
"displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "",
"type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}'
headers:
Expand All @@ -230,15 +230,15 @@ interactions:
Content-Encoding:
- gzip
Content-Length:
- '2595'
- '3266'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:33 GMT
- Tue, 16 Jun 2026 11:10:55 GMT
Pragma:
- no-cache
RequestId:
- 5a815f03-74e2-4496-aae0-2364a02687cd
- e36eba8a-b837-4f56-b1c2-1afe7bf5bdfc
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand All @@ -264,9 +264,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; Linux/6.12.76-linuxkit; Python/3.12.11)
method: GET
uri: https://api.fabric.microsoft.com/v1/workspaces/81517fa4-30e3-42e6-b751-b36af1c8e99a/items
uri: https://api.fabric.microsoft.com/v1/workspaces/fd1b2648-dbb2-442c-b4c7-73b02f7f8a2a/items
response:
body:
string: '{"value": []}'
Expand All @@ -282,11 +282,11 @@ interactions:
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 13 May 2026 11:03:34 GMT
- Tue, 16 Jun 2026 11:10:56 GMT
Pragma:
- no-cache
RequestId:
- 1283e8eb-846f-49ab-b1e4-4438ef0df0f9
- 8e6ad6b9-06c4-4219-8a9e-c95d2ad90cca
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand Down Expand Up @@ -314,9 +314,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; Linux/6.12.76-linuxkit; Python/3.12.11)
method: DELETE
uri: https://api.fabric.microsoft.com/v1/workspaces/81517fa4-30e3-42e6-b751-b36af1c8e99a
uri: https://api.fabric.microsoft.com/v1/workspaces/fd1b2648-dbb2-442c-b4c7-73b02f7f8a2a
response:
body:
string: ''
Expand All @@ -332,11 +332,11 @@ interactions:
Content-Type:
- application/octet-stream
Date:
- Wed, 13 May 2026 11:03:35 GMT
- Tue, 16 Jun 2026 11:10:57 GMT
Pragma:
- no-cache
RequestId:
- b0ec7a9f-0f36-4321-9c58-823c5894cd4c
- dfb8c411-66a0-4958-a7fe-8ff070df1400
Strict-Transport-Security:
- max-age=31536000; includeSubDomains
X-Content-Type-Options:
Expand Down
Loading
Loading