Skip to content
Closed
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
8 changes: 5 additions & 3 deletions src/azure-cli/azure/cli/command_modules/sql/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4672,11 +4672,13 @@ def server_update(

# Handle soft delete retention days
# 0 = disable soft delete, 1-7 = enable with specified retention days
# If not specified, set to None to avoid sending existing value to API
# The API may return -1 for legacy servers where soft delete was never configured.
# -1 is not a valid value for PUT requests, so normalize it to 0 (disabled)
# to avoid "Invalid value given for parameter RetentionDays" errors.
if soft_delete_retention_days is not None:
instance.retention_days = soft_delete_retention_days
else:
instance.retention_days = None
elif instance.retention_days is not None and instance.retention_days < 0:
instance.retention_days = 0

return instance

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
ClientAuthenticationType,
ClientType,
ComputeModelType,
ResourceIdType)
ResourceIdType,
server_update)
from datetime import datetime, timedelta

# Constants
Expand Down Expand Up @@ -9846,3 +9847,58 @@ def test_sql_server_restore_to_different_resource_group(self):
# Clean up both resource groups
self.cmd('group delete -n {} --yes --no-wait'.format(rg1_name))
self.cmd('group delete -n {} --yes --no-wait'.format(rg2_name))


class ServerUpdateRetentionDaysUnitTest(unittest.TestCase):
"""Unit tests for server_update retention_days handling."""

def _make_instance(self, retention_days):
"""Create a minimal mock server instance with the given retention_days value."""
from unittest.mock import MagicMock
instance = MagicMock()
instance.identity = None
instance.retention_days = retention_days
return instance

def test_retention_days_negative_one_normalized_to_zero(self):
"""When the server GET returns retention_days=-1 (legacy 'not configured' value)
and the user does not specify --soft-delete-retention-days,
server_update should normalize -1 to 0 (disabled) to avoid an API error."""
instance = self._make_instance(-1)
result = server_update(instance)
self.assertEqual(result.retention_days, 0)

def test_retention_days_none_not_modified(self):
"""When the server GET returns retention_days=None and the user does not specify
--soft-delete-retention-days, server_update should leave retention_days as None
(the field will be omitted from the PUT body)."""
instance = self._make_instance(None)
result = server_update(instance)
self.assertIsNone(result.retention_days)

def test_retention_days_zero_preserved(self):
"""When the server has retention_days=0 (soft delete disabled) and the user does
not specify --soft-delete-retention-days, the value should be preserved."""
instance = self._make_instance(0)
result = server_update(instance)
self.assertEqual(result.retention_days, 0)

def test_retention_days_positive_preserved(self):
"""When the server has retention_days=7 (soft delete enabled) and the user does
not specify --soft-delete-retention-days, the value should be preserved."""
instance = self._make_instance(7)
result = server_update(instance)
self.assertEqual(result.retention_days, 7)

def test_soft_delete_retention_days_specified_sets_value(self):
"""When the user specifies --soft-delete-retention-days, that value should be used
regardless of the existing retention_days."""
instance = self._make_instance(-1)
result = server_update(instance, soft_delete_retention_days=5)
self.assertEqual(result.retention_days, 5)

def test_soft_delete_retention_days_zero_disables(self):
"""When the user specifies --soft-delete-retention-days 0, soft delete is disabled."""
instance = self._make_instance(7)
result = server_update(instance, soft_delete_retention_days=0)
self.assertEqual(result.retention_days, 0)
Loading