Skip to content

Commit 596c068

Browse files
joratzCopilot
andauthored
Initial commit of endpoint registration migration (#15)
* Initial commit of endpoint registration migration * Add bot configurator interface, fix tests, and apply suggestions * Update src/Microsoft.Agents.A365.DevTools.Cli/Services/BotConfigurator.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Respond to comments * Remove test env vars * Update src/Microsoft.Agents.A365.DevTools.Cli/Services/BotConfigurator.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Microsoft.Agents.A365.DevTools.Cli/Models/Agent365Config.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add message for API errors * Respond to comments * Update default location * Revert default location update for now This reverts commit 26e7e7b. * Update src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/CleanupCommandTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/Microsoft.Agents.A365.DevTools.Cli/Services/BotConfigurator.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/DEVELOPER.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update error message * Temporarily set westus as default region * Respond to comments --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent fb000a7 commit 596c068

22 files changed

+877
-1613
lines changed

Readme-Usage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ a365 config init --global
5959
"tenantId": "your-tenant-id",
6060
"subscriptionId": "your-subscription-id",
6161
"resourceGroup": "rg-agent365-dev",
62-
"location": "eastus",
62+
"location": "westus",
6363
"webAppName": "webapp-agent365-dev",
6464
"agentIdentityDisplayName": "Agent 365 Development Agent",
6565
"agentUserPrincipalName": "agent.username@yourdomain.onmicrosoft.com",

docs/commands/config-init.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ Manager email [agent365demo.manager1@a365preview001.onmicrosoft.com]:
126126
Choose the Azure region for deployment:
127127

128128
```
129-
Azure location [eastus]:
129+
Azure location [westus]:
130130
```
131131

132132
**Smart Defaults**: Uses location from existing config or Azure account
@@ -149,7 +149,7 @@ Manager Email : agent365demo.manager1@a365preview001.onmicrosoft.com
149149
Deployment Path : C:\A365-Ignite-Demo\sample_agent
150150
Resource Group : a365demorg
151151
App Service Plan : a365agent-app-plan
152-
Location : eastus
152+
Location : westus
153153
Subscription : My Subscription (e09e22f2-9193-4f54-a335-01f59575eefd)
154154
Tenant : adfa4542-3e1e-46f5-9c70-3df0b15b3f6c
155155
@@ -195,7 +195,7 @@ The wizard automatically populates these fields:
195195
| **tenantId** | Azure AD Tenant ID | Azure CLI (`az account show`) | `adfa4542-3e1e-46f5-9c70-3df0b15b3f6c` |
196196
| **subscriptionId** | Azure Subscription ID | Azure CLI (`az account show`) | `e09e22f2-9193-4f54-a335-01f59575eefd` |
197197
| **resourceGroup** | Azure Resource Group name | User selection from list | `a365demorg` |
198-
| **location** | Azure region | Azure account or user input | `eastus` |
198+
| **location** | Azure region | Azure account or user input | `westus` |
199199
| **appServicePlanName** | App Service Plan name | User selection from list | `a365agent-app-plan` |
200200
| **appServicePlanSku** | Service Plan SKU | Default value | `B1` |
201201

@@ -242,7 +242,7 @@ After completing the wizard, `a365.config.json` is created:
242242
"tenantId": "adfa4542-3e1e-46f5-9c70-3df0b15b3f6c",
243243
"subscriptionId": "e09e22f2-9193-4f54-a335-01f59575eefd",
244244
"resourceGroup": "a365demorg",
245-
"location": "eastus",
245+
"location": "westus",
246246
"environment": "prod",
247247
"appServicePlanName": "a365agent-app-plan",
248248
"appServicePlanSku": "B1",

src/DEVELOPER.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,38 @@ For security and flexibility, the CLI supports environment variable overrides fo
466466
export POWERPLATFORM_API_URL=https://api.custom.powerplatform.example.com
467467
```
468468

469+
6. **Create endpoint URL**:
470+
```bash
471+
# Override create endpoint URL (for custom environments)
472+
# Internal use only - for non-production Microsoft environments
473+
export A365_CREATE_ENDPOINT_STAGING=https://staging.agent365.example.com/agents/createAgentBlueprint
474+
export A365_CREATE_ENDPOINT_CUSTOM=https://custom.agent365.example.com/agents/createAgentBlueprint
475+
```
476+
477+
7. **Delete endpoint URL**:
478+
```bash
479+
# Override delete endpoint URL (for custom environments)
480+
# Internal use only - for non-production Microsoft environments
481+
export A365_DELETE_ENDPOINT_STAGING=https://staging.agent365.example.com/agents/deleteAgentBlueprint
482+
export A365_DELETE_ENDPOINT_CUSTOM=https://custom.agent365.example.com/agents/deleteAgentBlueprint
483+
```
484+
485+
8. **Endpoint deployment Environment**:
486+
```bash
487+
# Override endpoint deployment environment (for custom environments)
488+
# Internal use only - for non-production Microsoft environments
489+
export A365_DEPLOYMENT_ENVIRONMENT_STAGING=staging
490+
export A365_DEPLOYMENT_ENVIRONMENT_CUSTOM=custom
491+
```
492+
493+
9. **Endpoint cluster category**:
494+
```bash
495+
# Override endpoint cluster category (for custom environments)
496+
# Internal use only - for non-production Microsoft environments
497+
export A365_CLUSTER_CATEGORY_STAGING=staging
498+
export A365_CLUSTER_CATEGORY_CUSTOM=custom
499+
```
500+
469501
**Implementation Pattern**:
470502

471503
**ConfigConstants.cs** (Per-environment with suffix):

src/Microsoft.Agents.A365.DevTools.Cli/Commands/CleanupCommand.cs

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.CommandLine;
55
using System.Text.Json;
66
using Microsoft.Extensions.Logging;
7+
using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers;
78
using Microsoft.Agents.A365.DevTools.Cli.Services;
89
using Microsoft.Agents.A365.DevTools.Cli.Models;
910

@@ -14,6 +15,7 @@ public class CleanupCommand
1415
public static Command CreateCommand(
1516
ILogger<CleanupCommand> logger,
1617
IConfigService configService,
18+
IBotConfigurator botConfigurator,
1719
CommandExecutor executor)
1820
{
1921
var cleanupCommand = new Command("cleanup", "Clean up ALL resources (blueprint, instance, Azure) - use subcommands for granular cleanup");
@@ -31,12 +33,12 @@ public static Command CreateCommand(
3133
// Set default handler for 'a365 cleanup' (without subcommand) - cleans up everything
3234
cleanupCommand.SetHandler(async (configFile) =>
3335
{
34-
await ExecuteAllCleanupAsync(logger, configService, executor, configFile);
36+
await ExecuteAllCleanupAsync(logger, configService, botConfigurator, executor, configFile);
3537
}, configOption);
3638

3739
// Add subcommands for granular control
3840
cleanupCommand.AddCommand(CreateBlueprintCleanupCommand(logger, configService, executor));
39-
cleanupCommand.AddCommand(CreateAzureCleanupCommand(logger, configService, executor));
41+
cleanupCommand.AddCommand(CreateAzureCleanupCommand(logger, configService, botConfigurator, executor));
4042
cleanupCommand.AddCommand(CreateInstanceCleanupCommand(logger, configService, executor));
4143

4244
return cleanupCommand;
@@ -118,6 +120,7 @@ private static Command CreateBlueprintCleanupCommand(
118120
private static Command CreateAzureCleanupCommand(
119121
ILogger<CleanupCommand> logger,
120122
IConfigService configService,
123+
IBotConfigurator botConfigurator,
121124
CommandExecutor executor)
122125
{
123126
var command = new Command("azure", "Remove Azure resources (App Service, App Service Plan)");
@@ -143,11 +146,11 @@ private static Command CreateAzureCleanupCommand(
143146
logger.LogInformation("");
144147
logger.LogInformation("Azure Cleanup Preview:");
145148
logger.LogInformation("=========================");
146-
logger.LogInformation(" Web App: {WebAppName}", config.WebAppName);
147-
logger.LogInformation(" App Service Plan: {PlanName}", config.AppServicePlanName);
149+
logger.LogInformation(" Web App: {WebAppName}", config.WebAppName);
150+
logger.LogInformation(" App Service Plan: {PlanName}", config.AppServicePlanName);
148151
if (!string.IsNullOrEmpty(config.BotId))
149-
logger.LogInformation(" Azure Bot: {BotId}", config.BotId);
150-
logger.LogInformation(" Resource Group: {ResourceGroup}", config.ResourceGroup);
152+
logger.LogInformation(" Azure Bot: {BotId}", config.BotId);
153+
logger.LogInformation(" Resource Group: {ResourceGroup}", config.ResourceGroup);
151154
logger.LogInformation("");
152155

153156
Console.Write("Continue with Azure cleanup? (y/N): ");
@@ -166,9 +169,27 @@ private static Command CreateAzureCleanupCommand(
166169
};
167170

168171
// Add bot deletion if bot exists
169-
if (!string.IsNullOrEmpty(config.BotName) && !string.IsNullOrEmpty(config.ResourceGroup))
172+
if (!string.IsNullOrEmpty(config.BotName))
170173
{
171-
commandsList.Add(($"az bot delete --name {config.BotName} --resource-group {config.ResourceGroup}", "Azure Bot"));
174+
logger.LogInformation("Deleting messaging endpoint registration...");
175+
if (string.IsNullOrEmpty(config.AgentBlueprintId))
176+
{
177+
logger.LogError("Agent Blueprint ID not found. Agent Blueprint ID is required for deleting endpoint registration.");
178+
}
179+
else
180+
{
181+
var endpointName = EndpointHelper.GetEndpointName(config.BotName);
182+
183+
var endpointRegistered = await botConfigurator.DeleteEndpointWithAgentBlueprintAsync(
184+
endpointName,
185+
config.Location,
186+
config.AgentBlueprintId);
187+
188+
if (!endpointRegistered)
189+
{
190+
logger.LogWarning("Failed to delete blueprint messaging endpoint");
191+
}
192+
}
172193
}
173194

174195
var commands = commandsList.ToArray();
@@ -231,10 +252,10 @@ private static Command CreateInstanceCleanupCommand(
231252
logger.LogInformation("Will delete the following resources:");
232253

233254
if (!string.IsNullOrEmpty(config.AgenticAppId))
234-
logger.LogInformation(" Agent Identity Application: {IdentityId}", config.AgenticAppId);
255+
logger.LogInformation(" Agent Identity Application: {IdentityId}", config.AgenticAppId);
235256
if (!string.IsNullOrEmpty(config.AgenticUserId))
236-
logger.LogInformation(" Agent User: {UserId}", config.AgenticUserId);
237-
logger.LogInformation(" Generated configuration file");
257+
logger.LogInformation(" Agent User: {UserId}", config.AgenticUserId);
258+
logger.LogInformation(" Generated configuration file");
238259
logger.LogInformation("");
239260

240261
Console.Write("Continue with instance cleanup? (y/N): ");
@@ -319,6 +340,7 @@ private static Command CreateInstanceCleanupCommand(
319340
private static async Task ExecuteAllCleanupAsync(
320341
ILogger<CleanupCommand> logger,
321342
IConfigService configService,
343+
IBotConfigurator botConfigurator,
322344
CommandExecutor executor,
323345
FileInfo? configFile)
324346
{
@@ -334,18 +356,18 @@ private static async Task ExecuteAllCleanupAsync(
334356
logger.LogInformation("============================");
335357
logger.LogInformation("WARNING: ALL RESOURCES WILL BE DELETED:");
336358
if (!string.IsNullOrEmpty(config.AgentBlueprintId))
337-
logger.LogInformation(" Blueprint Application: {BlueprintId}", config.AgentBlueprintId);
359+
logger.LogInformation(" Blueprint Application: {BlueprintId}", config.AgentBlueprintId);
338360
if (!string.IsNullOrEmpty(config.AgenticAppId))
339-
logger.LogInformation(" Agent Identity Application: {IdentityId}", config.AgenticAppId);
361+
logger.LogInformation(" Agent Identity Application: {IdentityId}", config.AgenticAppId);
340362
if (!string.IsNullOrEmpty(config.AgenticUserId))
341-
logger.LogInformation(" Agent User: {UserId}", config.AgenticUserId);
363+
logger.LogInformation(" Agent User: {UserId}", config.AgenticUserId);
342364
if (!string.IsNullOrEmpty(config.WebAppName))
343-
logger.LogInformation(" Web App: {WebAppName}", config.WebAppName);
365+
logger.LogInformation(" Web App: {WebAppName}", config.WebAppName);
344366
if (!string.IsNullOrEmpty(config.AppServicePlanName))
345-
logger.LogInformation(" App Service Plan: {PlanName}", config.AppServicePlanName);
367+
logger.LogInformation(" App Service Plan: {PlanName}", config.AppServicePlanName);
346368
if (!string.IsNullOrEmpty(config.BotName))
347-
logger.LogInformation(" Azure Bot: {BotName}", config.BotName);
348-
logger.LogInformation(" Generated configuration file");
369+
logger.LogInformation(" Azure Messaging Endpoint: {BotName}", config.BotName);
370+
logger.LogInformation(" Generated configuration file");
349371
logger.LogInformation("");
350372

351373
Console.Write("Are you sure you want to DELETE ALL resources? (y/N): ");
@@ -395,12 +417,28 @@ private static async Task ExecuteAllCleanupAsync(
395417
{
396418
logger.LogInformation("Deleting Azure resources...");
397419

398-
// Delete Azure Bot first (independent resource)
420+
// Add bot deletion if bot exists
399421
if (!string.IsNullOrEmpty(config.BotName))
400422
{
401-
logger.LogInformation("Deleting Azure Bot: {BotName}...", config.BotName);
402-
await executor.ExecuteAsync("az", $"bot delete --name {config.BotName} --resource-group {config.ResourceGroup}", null, true, false, CancellationToken.None);
403-
logger.LogInformation("Azure Bot deleted");
423+
logger.LogInformation("Deleting messaging endpoint registration...");
424+
if (string.IsNullOrEmpty(config.AgentBlueprintId))
425+
{
426+
logger.LogError("Agent Blueprint ID not found. Agent Blueprint ID is required for deleting endpoint registration.");
427+
}
428+
else
429+
{
430+
var endpointName = EndpointHelper.GetEndpointName(config.BotName);
431+
432+
var endpointRegistered = await botConfigurator.DeleteEndpointWithAgentBlueprintAsync(
433+
endpointName,
434+
config.Location,
435+
config.AgentBlueprintId);
436+
437+
if (!endpointRegistered)
438+
{
439+
logger.LogWarning("Failed to delete blueprint messaging endpoint");
440+
}
441+
}
404442
}
405443

406444
// Delete Web App

src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Agents.A365.DevTools.Cli.Helpers;
66
using Microsoft.Agents.A365.DevTools.Cli.Models;
77
using Microsoft.Agents.A365.DevTools.Cli.Services;
8+
using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers;
89
using Microsoft.Extensions.Logging;
910
using System.CommandLine;
1011
using System.Text.Json;
@@ -17,7 +18,7 @@ namespace Microsoft.Agents.A365.DevTools.Cli.Commands;
1718
public class CreateInstanceCommand
1819
{
1920
public static Command CreateCommand(ILogger<CreateInstanceCommand> logger, IConfigService configService, CommandExecutor executor,
20-
BotConfigurator botConfigurator, GraphApiService graphApiService, IAzureValidator azureValidator)
21+
IBotConfigurator botConfigurator, GraphApiService graphApiService, IAzureValidator azureValidator)
2122
{
2223
var command = new Command("create-instance", "Create and configure agent user identities with appropriate\nlicenses and notification settings for your deployed agent");
2324

@@ -175,8 +176,9 @@ public static Command CreateCommand(ILogger<CreateInstanceCommand> logger, IConf
175176
var agentUserConfigPath = Path.Combine(Environment.CurrentDirectory, "agenticuser.config.json");
176177
string? agenticAppId = instanceConfig.AgenticAppId;
177178
string? agenticUserId = instanceConfig.AgenticUserId;
178-
var endpointName = $"{instanceConfig.WebAppName}-endpoint";
179-
179+
var baseEndpointName = $"{instanceConfig.WebAppName}-endpoint";
180+
var endpointName = EndpointHelper.GetEndpointName(baseEndpointName);
181+
180182
if (File.Exists(agentUserConfigPath))
181183
{
182184
logger.LogInformation(" - Reading agent identity from agenticuser.config.json");
@@ -217,24 +219,10 @@ public static Command CreateCommand(ILogger<CreateInstanceCommand> logger, IConf
217219
// Update configuration with the populated values
218220
logger.LogInformation("Updating configuration with generated values...");
219221

220-
// Get the actual Bot ID (Microsoft App ID) from Azure
221-
logger.LogInformation(" Querying Bot ID from Azure portal...");
222-
var botConfig = await botConfigurator.GetBotConfigurationAsync(instanceConfig.ResourceGroup, endpointName);
223-
var actualBotId = botConfig?.Properties?.MsaAppId ?? endpointName;
224-
225-
if (!string.IsNullOrEmpty(botConfig?.Properties?.MsaAppId))
226-
{
227-
logger.LogInformation(" Retrieved Microsoft App ID: {AppId}", botConfig.Properties.MsaAppId);
228-
}
229-
else
230-
{
231-
logger.LogWarning(" Could not retrieve Microsoft App ID from Azure, using bot name as fallback");
232-
}
233-
234222
// Update Agent365Config state properties
235-
instanceConfig.BotId = actualBotId;
236-
instanceConfig.BotMsaAppId = botConfig?.Properties?.MsaAppId;
237-
instanceConfig.BotMessagingEndpoint = botConfig?.Properties?.Endpoint;
223+
instanceConfig.BotId = instanceConfig.AgentBlueprintId ?? endpointName;
224+
instanceConfig.BotMsaAppId = instanceConfig.AgentBlueprintId;
225+
instanceConfig.BotMessagingEndpoint = $"https://{instanceConfig.WebAppName}.azurewebsites.net/api/messages";
238226

239227
logger.LogInformation(" Agent Blueprint ID: {AgentBlueprintId}", instanceConfig.AgentBlueprintId);
240228
logger.LogInformation(" Agent Instance ID: {AgenticAppId}", instanceConfig.AgenticAppId);

src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommand.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,16 +216,16 @@ public static Command CreateCommand(
216216
logger.LogInformation("Your manifest has been updated at: {ManifestPath}", manifestPath);
217217
logger.LogInformation("");
218218
logger.LogInformation("Please customize these fields before publishing:");
219-
logger.LogInformation(" Version ('version'): Increment for republishing (e.g., 1.0.0 to 1.0.1)");
219+
logger.LogInformation(" Version ('version'): Increment for republishing (e.g., 1.0.0 to 1.0.1)");
220220
logger.LogInformation(" REQUIRED: Must be higher than previously published version");
221-
logger.LogInformation(" Agent Name ('name.short' and 'name.full'): Make it descriptive and user-friendly");
221+
logger.LogInformation(" Agent Name ('name.short' and 'name.full'): Make it descriptive and user-friendly");
222222
logger.LogInformation(" Currently: {Name}", agentBlueprintDisplayName);
223223
logger.LogInformation(" IMPORTANT: 'name.short' must be 30 characters or less");
224-
logger.LogInformation(" Descriptions ('description.short' and 'description.full'): Explain what your agent does");
224+
logger.LogInformation(" Descriptions ('description.short' and 'description.full'): Explain what your agent does");
225225
logger.LogInformation(" Short: 1-2 sentences, Full: Detailed capabilities");
226-
logger.LogInformation(" Developer Info ('developer.name', 'developer.websiteUrl', 'developer.privacyUrl')");
226+
logger.LogInformation(" Developer Info ('developer.name', 'developer.websiteUrl', 'developer.privacyUrl')");
227227
logger.LogInformation(" Should reflect your organization details");
228-
logger.LogInformation(" Icons: Replace 'color.png' and 'outline.png' with your custom branding");
228+
logger.LogInformation(" Icons: Replace 'color.png' and 'outline.png' with your custom branding");
229229
logger.LogInformation("");
230230
logger.LogInformation("When you're done customizing, type 'continue' (or 'c') and press Enter to proceed:");
231231

0 commit comments

Comments
 (0)