Skip to content

[ResilienceManagement] Add create commands (namespace: resilience) - #3166

Open
adishiritwick wants to merge 4 commits into
microsoft:mainfrom
adishiritwick:adishi/createusagepattern
Open

[ResilienceManagement] Add create commands (namespace: resilience)#3166
adishiritwick wants to merge 4 commits into
microsoft:mainfrom
adishiritwick:adishi/createusagepattern

Conversation

@adishiritwick

@adishiritwick adishiritwick commented Jul 28, 2026

Copy link
Copy Markdown

Adds the authoring (create-or-update) commands to the Azure Resilience Management toolset (Azure.Mcp.Tools.ResilienceManagement, command namespace resilience).

This is PR 2 of the rollout plan in #2894 — building on the read-only surface delivered in #2948. It adds create commands across the usage-plan command groups, reusing the toolset plumbing established in PR 1 (IAreaSetup, BaseAzureResourceService, non-standard serviceGroup path-parameter handling, parameter shapes, telemetry, and recorded-test infrastructure). Lifecycle/action commands follow in PR 3.

All commands are create-or-update (ReadOnly = false, Destructive = true, Idempotent = true). Each returns the created/updated resource's details.

Commands added:

Usage Plan
resilience usageplan create (UsagePlans_CreateOrUpdate)
resilience usageplan enrollment create (Enrollments_CreateOrUpdate)
Also includes unit tests, recorded live tests (goal template/assignment, usage plan, enrollment), README/command docs/e2e prompts, and a changelog entry.

GitHub issue number?

[Link to the GitHub issue this PR addresses]

Pre-merge Checklist

  • Required for All PRs
    • Read contribution guidelines
    • PR title clearly describes the change
    • Commit history is clean with descriptive messages (cleanup guide)
    • Added comprehensive tests for new/modified functionality
    • Created a changelog entry if the change falls among the following: new feature, bug fix, UI/UX update, breaking change, or updated dependencies. Follow the changelog entry guide
  • For MCP tool changes:
    • One tool per PR: This PR adds or modifies only one MCP tool for faster review cycles
    • Updated servers/Azure.Mcp.Server/README.md and/or servers/Fabric.Mcp.Server/README.md documentation
    • Validate README.md changes running the script ./eng/scripts/Process-PackageReadMe.ps1. See Package README
    • For new or modified tool descriptions, ran ToolDescriptionEvaluator and obtained a score of 0.4 or more and a top 3 ranking for all related test prompts
    • For tools with new names, including new tools or renamed tools, update consolidated-tools.json
    • For renamed tools, follow the Tool Rename Checklist and tag the PR with the breaking-change label
    • For new tools associated with Azure services or publicly available tools/APIs/products, add URL to documentation in the PR description
  • Extra steps for Azure MCP Server tool changes:
    • Updated command list in servers/Azure.Mcp.Server/docs/azmcp-commands.md
    • Ran ./eng/scripts/Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • Updated test prompts in servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
    • 👉 For Community (non-Microsoft team member) PRs:
      • Security review: Reviewed code for security vulnerabilities, malicious code, or suspicious activities before running tests (crypto mining, spam, data exfiltration, etc.)
      • Manual tests run: added comment /azp run mcp - pullrequest - live to run Live Test Pipeline

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your contribution adishiritwick! We will review the pull request and get back to you soon.

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 Resilience Management “create” operations to the resilience namespace, extending the toolset beyond read-only scenarios by enabling usage plan and enrollment creation via ARM, along with unit/live test coverage and documentation/tooling updates.

Changes:

  • Added azmcp resilience usageplan create and azmcp resilience usageplan enrollment create commands, wired through IResilienceManagementService.
  • Expanded live test infrastructure and added unit/integration tests for the new create commands.
  • Updated Azure MCP Server docs/prompts, consolidated tool mappings, and changelog entry.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/Azure.Mcp.Tools.ResilienceManagement/tests/test-resources.bicep Adds outputs for isolated “create” test resource names.
tools/Azure.Mcp.Tools.ResilienceManagement/tests/test-resources-post.ps1 Creates isolated RG/service group for create live tests (note: outside harness-managed RG).
tools/Azure.Mcp.Tools.ResilienceManagement/tests/Azure.Mcp.Tools.ResilienceManagement.Tests/UsagePlans/UsagePlanCreateCommandTests.cs New unit tests for usage plan create command validation/results/errors.
tools/Azure.Mcp.Tools.ResilienceManagement/tests/Azure.Mcp.Tools.ResilienceManagement.Tests/UsagePlans/Enrollments/UsagePlanEnrollmentCreateCommandTests.cs New unit tests for enrollment create command validation/results/errors.
tools/Azure.Mcp.Tools.ResilienceManagement/tests/Azure.Mcp.Tools.ResilienceManagement.Tests/ResilienceManagementCommandTests.cs Adds live/integration scenarios for creating usage plans and enrollments.
tools/Azure.Mcp.Tools.ResilienceManagement/tests/Azure.Mcp.Tools.ResilienceManagement.Tests/assets.json Updates recorded-test assets tag.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Services/ResilienceManagementService.cs Implements ARM create/update flows for usage plans and enrollments.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Services/IResilienceManagementService.cs Extends service interface with create APIs.
tools/Azure.Mcp.Tools.ResilienceManagement/src/ResilienceManagementSetup.cs Registers new commands and adds them to command groups.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Options/UsagePlans/UsagePlanCreateOption.cs Adds options for usage plan creation.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Options/UsagePlans/Enrollments/UsagePlanEnrollmentCreateOption.cs Adds options for enrollment creation.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Commands/UsagePlans/UsagePlanCreateCommand.cs New command implementation + error mapping for usage plan create.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Commands/UsagePlans/Enrollments/UsagePlanEnrollmentCreateCommand.cs New command implementation + error mapping for enrollment create.
tools/Azure.Mcp.Tools.ResilienceManagement/src/Commands/ResilienceManagementJsonContext.cs Registers new response models for AOT-safe JSON serialization.
servers/Azure.Mcp.Server/src/Resources/consolidated-tools.json Adds a consolidated “create” tool mapping for the new commands.
servers/Azure.Mcp.Server/README.md Adds example prompts for the new create scenarios.
servers/Azure.Mcp.Server/docs/e2eTestPrompts.md Adds E2E prompts for the new tool IDs.
servers/Azure.Mcp.Server/docs/azmcp-commands.md Adds CLI docs for the new create commands.
servers/Azure.Mcp.Server/changelog-entries/1782549900000.yaml Adds changelog entries for the new features.

Comment thread servers/Azure.Mcp.Server/src/Resources/consolidated-tools.json
Comment thread tools/Azure.Mcp.Tools.ResilienceManagement/tests/test-resources-post.ps1 Outdated

@RickWinter Rick Winter (RickWinter) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Noticed a couple things

# and carries the same Owners/DeleteAfter tags as the managed resource group so subscription-wide
# expiry-based clean-up (see New-TestResources.ps1's DeleteAfterHours) reclaims it automatically.
$managedResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName
New-AzResourceGroup -Name $createResourceGroupName -Location $managedResourceGroup.Location -Tag $managedResourceGroup.Tags -Force | Out-Null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This resource group is created after New-TestResources.ps1 grants the test identity Owner only on the harness-managed resource group. The live tests call the new command as that test identity, so creating a usage plan in $createResourceGroupName will fail with 403 in CI unless the identity already has subscription-wide access. Pass TestApplicationOid into this script and grant it the required role on the new resource group, or keep the create test resources inside the managed group.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Addressed. Please check

@adishiritwick
adishiritwick force-pushed the adishi/createusagepattern branch from 35a6f91 to 2c90f10 Compare August 6, 2026 05:34

@g2vinay Vinay Gera (g2vinay) 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.

Thanks for adding this authoring surface. The inline comments cover the specific comments.

private readonly ILogger<UsagePlanCreateCommand> _logger = logger;
private readonly IResilienceManagementService _resilienceManagementService = resilienceManagementService;

public override async Task<CommandResponse> ExecuteAsync(CommandContext context, UsagePlanCreateOptions options, CancellationToken cancellationToken)

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.

Please add ValidateOptions for --usage-plan. The API requires usage plan names to match ^[a-zA-Z0-9-]{3,24}$, but the command currently accepts any non-empty string. Please also add negative tests for malformed, oversized, and path-like values.

private readonly ILogger<UsagePlanEnrollmentCreateCommand> _logger = logger;
private readonly IResilienceManagementService _resilienceManagementService = resilienceManagementService;

public override async Task<CommandResponse> ExecuteAsync(CommandContext context, UsagePlanEnrollmentCreateOptions options, CancellationToken cancellationToken)

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.

Please validate --usage-plan, --enrollment, and --service-group using their documented Azure naming rules before they are used in ARM resource identifiers. Usage plan and enrollment names must match ^[a-zA-Z0-9-]{3,24}$. Please include negative tests for malformed, oversized, and path-like values.

Comment on lines +20 to +24
Title = "Create Resilience Usage Plan",
Description = """
Creates a resilience usage plan in the specified resource group with the given plan type, and returns
the created usage plan information including id, name, resource type, location, tags, plan type, and
provisioning state.

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.

The service uses CreateOrUpdateAsync, but this metadata presents the command as create-only. Please describe the create-or-update behavior consistently so users understand that an existing usage plan may be modified.

Comment on lines +68 to +69
RequestFailedException reqEx when reqEx.Status == (int)HttpStatusCode.Conflict =>
"Usage plan name already exists. Choose a different name.",

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.

Since this is a create-or-update operation, an existing name should normally be valid. Is every HTTP 409 from this API guaranteed to mean a name collision? Please check a documented Azure error code before returning this message, or use a sanitized generic conflict message.

$"Authorization failed creating the usage plan enrollment. Details: {reqEx.Message}",
RequestFailedException reqEx when reqEx.Status == (int)HttpStatusCode.NotFound =>
"Usage plan or service group not found. Verify they exist and you have access.",
RequestFailedException reqEx => reqEx.Message,

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.

Please replace the raw Azure exception message with a sanitized fallback message. Backend payloads should not be returned directly to callers.

"resilience_usageplan_create",
new()
{
{ "subscription", Settings.SubscriptionId },

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.

Please pass { "tenant", Settings.TenantId } to each new recorded-test tool call, including both calls in the enrollment test. Otherwise, these tests can fail when the subscription is not in the default tenant.

Comment on lines +904 to +905
| resilience_usageplan_create | Create a resilience usage plan <usage_plan_name> with plan type Basic in resource group <resource_group_name> |
| resilience_usageplan_enrollment_create | Create a usage plan enrollment <enrollment_name> for usage plan <usage_plan_name> associated with service group <service_group> in resource group <resource_group_name> |

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.

Please add 2–3 realistic prompt variants for each new tool, as required by the tool-development guide. One exact phrasing per tool provides limited coverage for ToolDescriptionEvaluator and routing behavior.

Assert.NotEmpty(command.Description);
}

[Theory]

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.

Please add negative tests for invalid usage-plan, enrollment, and service-group names. The current tests verify only whether required options are present.

* "List all resilience recovery plans in service group 'my-service-group'"
* "Get the recovery plan 'my-recovery-plan' in service group 'my-service-group'"
* "List the recovery jobs of recovery plan 'my-recovery-plan' in service group 'my-service-group'"
* "Create a resilience usage plan 'my-plan' in resource group 'my-rg'"

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.

--plan-type is required, but this example does not provide one. Please make it complete, for example: "Create a Basic resilience usage plan 'my-plan' in resource group 'my-rg'."

@@ -0,0 +1,5 @@
changes:
- section: "Features Added"
description: "Added the 'azmcp resilience usageplan create' command to create a resilience usage plan in a resource group, including its plan type."

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.

The implementation performs create-or-update. Please use that wording here so the changelog accurately describes the behavior.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants