Skip to content

[HorizonDB] Add restore command#10049

Draft
alxhghs wants to merge 9 commits into
Azure:mainfrom
alxhghs:alxhghs/alexfen-horizondb-restore-operations
Draft

[HorizonDB] Add restore command#10049
alxhghs wants to merge 9 commits into
Azure:mainfrom
alxhghs:alxhghs/alexfen-horizondb-restore-operations

Conversation

@alxhghs

@alxhghs alxhghs commented Jun 29, 2026

Copy link
Copy Markdown
Member

Description

Adds az horizondb restore to create a new HorizonDB cluster as a point-in-time restore of an existing source cluster.

  • restore — restore a HorizonDB cluster from a source cluster. Accepts --source-cluster and an optional --restore-time (RFC3339). When --restore-time is omitted it defaults to the current UTC time. The command sends createMode=PointInTimeRestore with the required PointInTimeUTC.

Mirrors the az postgres flexible-server restore convention (--restore-time, optional, default = now, parsed/validated with dateutil).

Note: the service currently requires the restore point to be at least ~5 minutes in the past (a temporary preview buffer), so supply an explicit older --restore-time if a restore very close to "now" is rejected.

Bumps the extension version to 1.0.086 and documents the change in HISTORY.rst / README.md.

Testing

  • azdev style horizondb — PASSED
  • azdev linter horizondb — PASSED
  • HorizonDBClusterMgmtScenarioTest recorded live (create → show → list → update → restore → delete) and verified in playback — PASSED

History Notes

  • Add support for restoring HorizonDB clusters through az horizondb restore.

🤖 PR Validation — ⚠️ Review suggested

Breaking Changes
⚠️ None
⚠️Azure CLI Extensions Breaking Change Test
⚠️horizondb
rule cmd_name rule_message suggest_message
⚠️ 1001 - CmdAdd horizondb restore cmd horizondb restore added

Alex Fenwood Hughes and others added 3 commits June 26, 2026 14:16
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The `az horizondb restore` command sent createMode=PointInTimeRestore and
sourceClusterResourceId but omitted pointInTimeUTC, which the service requires
(MissingRequiredParameter). Add a `--restore-time` argument (optional, defaults
to current UTC time, parse-validated) mirroring `az postgres flexible-server
restore`, and pass it as point_in_time_utc.

- _params.py: add --restore-time arg with current-time default.
- custom_commands.py: parse --restore-time and set point_in_time_utc.
- _help.py: add point-in-time restore example.
- test: supply a valid restore time (utcnow - 6 min, clearing the 300s preview
  buffer) and assert createMode; re-record live cassette and commit test log.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-client-tools-bot-prd

azure-client-tools-bot-prd Bot commented Jun 29, 2026

Copy link
Copy Markdown
⚠️Azure CLI Extensions Breaking Change Test
⚠️horizondb
rule cmd_name rule_message suggest_message
⚠️ 1001 - CmdAdd horizondb restore cmd horizondb restore added

@yonzhan
yonzhan requested a review from Pan-Qi June 29, 2026 23:06
@yonzhan
yonzhan requested a review from jsntcy June 29, 2026 23:06
@yonzhan

yonzhan commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

HorizonDB

…izondb-restore-operations

# Conflicts:
#	src/horizondb/HISTORY.rst
#	src/horizondb/azext_horizondb/_params.py

@Pan-Qi Pan-Qi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. please resolve the conflict
  2. please mark as open if this PR is ready for review

Comment thread src/horizondb/azext_horizondb/_help.py Outdated
Comment thread src/horizondb/azext_horizondb/_help.py Outdated
Comment thread src/horizondb/azext_horizondb/_help.py Outdated
Comment thread src/horizondb/azext_horizondb/_help.py Outdated
Comment thread src/horizondb/azext_horizondb/_params.py Outdated
Comment thread src/horizondb/azext_horizondb/commands/custom_commands.py Outdated
Comment thread src/horizondb/azext_horizondb/commands/custom_commands.py Outdated
Comment thread src/horizondb/azext_horizondb/_params.py Outdated
Comment thread src/horizondb/README.md Outdated
Comment thread src/horizondb/azext_horizondb/_params.py Outdated
@kabharati

Copy link
Copy Markdown

Thanks @nachoalonsoportillo for making these changes.

Alex Fenwood Hughes and others added 2 commits July 14, 2026 11:00
- Clarify restore help/summary wording and examples
- Reword source-cluster arg and error message (resource identifier)
- Default restore-time to 6 minutes before now during preview when omitted
- Update example timestamps

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…izondb-restore-operations

# Conflicts:
#	src/horizondb/HISTORY.rst
#	src/horizondb/azext_horizondb/commands/custom_commands.py
#	src/horizondb/azext_horizondb/tests/latest/recordings/test_horizondb_cluster_mgmt.yaml
@alxhghs
alxhghs marked this pull request as ready for review July 14, 2026 20:01
@alxhghs
alxhghs requested review from Pan-Qi and Copilot July 14, 2026 20:01
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@alxhghs

alxhghs commented Jul 14, 2026

Copy link
Copy Markdown
Member Author
  1. please resolve the conflict
  2. please mark as open if this PR is ready for review

Hi @Pan-Qi, I resolved the merge conflict and published the PR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new az horizondb restore command to create a HorizonDB cluster via point-in-time restore from an existing source cluster, and updates the extension’s docs/tests/versioning to reflect the new capability.

Changes:

  • Introduces horizondb restore command wiring plus implementation that sets createMode=PointInTimeRestore and sends the restore point timestamp.
  • Adds new CLI parameters/help for --source-cluster and --restore-time, plus scenario test coverage for restore.
  • Bumps extension version and documents the change in HISTORY/README.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/horizondb/setup.py Bumps extension version.
src/horizondb/README.md Documents the new restore command in the feature list.
src/horizondb/HISTORY.rst Adds release notes entry for restore support.
src/horizondb/azext_horizondb/tests/latest/test_horizondb_commands.py Extends scenario test to perform a restore and cleanup.
src/horizondb/azext_horizondb/commands/custom_commands.py Implements restore logic (source cluster resolution + restore-time parsing).
src/horizondb/azext_horizondb/cluster_commands.py Registers horizondb restore in the command table.
src/horizondb/azext_horizondb/_params.py Adds --source-cluster and --restore-time arguments.
src/horizondb/azext_horizondb/_help.py Adds help + examples for horizondb restore.

Comment on lines +104 to +116
def _parse_restore_time(restore_time):
import datetime
if restore_time is None:
# During preview, default to 6 minutes before now to satisfy the minimum 5-minute buffer.
return datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0) - datetime.timedelta(minutes=6)
from dateutil import parser
try:
return parser.parse(restore_time)
except (ValueError, OverflowError):
raise InvalidArgumentValueError(
"The restore time value has an incorrect date format. "
"Please use ISO8601 format, e.g., 2026-07-15T02:10:00+00:00.")

Comment on lines +106 to +108
if restore_time is None:
# During preview, default to 6 minutes before now to satisfy the minimum 5-minute buffer.
return datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0) - datetime.timedelta(minutes=6)
Comment on lines +75 to +93
if self.is_live:
from datetime import datetime, timedelta, timezone

restored_cluster_name = self.create_random_name(CLUSTER_NAME_PREFIX, CLUSTER_NAME_MAX_LENGTH)

# Restore time must be at least 5 minutes (300s) before the current time during preview.
restore_time = (datetime.now(timezone.utc) - timedelta(minutes=6)).replace(microsecond=0).isoformat()

# Restore cluster
restore_result = self.cmd('horizondb restore -g {} -n {} --source-cluster {} --restore-time {}'.format(
resource_group, restored_cluster_name, cluster_name, restore_time)).get_output_in_json()

self.assertEqual(restore_result['name'], restored_cluster_name)
self.assertEqual(restore_result['properties']['createMode'], 'PointInTimeRestore')

# Delete restored cluster
self.cmd('horizondb delete -g {} -n {} --yes'.format(resource_group, restored_cluster_name),
checks=NoneCheck())

Comment thread src/horizondb/azext_horizondb/_help.py Outdated
Comment thread src/horizondb/setup.py Outdated
@Pan-Qi

Pan-Qi commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

@Pan-Qi

Pan-Qi commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@alxhghs kindly ping for resolving the failed tests

alxhghs and others added 2 commits July 23, 2026 08:52
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ight

# Conflicts:
#	src/horizondb/HISTORY.rst
@alxhghs
alxhghs marked this pull request as draft July 23, 2026 16:49
- Normalize --restore-time to a UTC-aware datetime in _parse_restore_time:
  a value without an explicit offset is interpreted as UTC and an
  offset-aware value is converted to UTC, so the service never receives a
  naive/ambiguous datetime.
- Run the restore scenario in playback (not just live) so `az horizondb
  restore` is actually exercised by the recorded cassette. Playback matches
  on method + URI only, so the computed restore-time is not replay-sensitive.
- Add unit tests for _parse_restore_time (default, naive, offset-aware, Z
  suffix, invalid).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9af6f71f-2404-4076-ba3f-b6730e166e91
@a0x1ab

a0x1ab commented Jul 23, 2026

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants