diff --git a/tools/Azure.Mcp.Tools.Deploy/src/Services/DeployService.cs b/tools/Azure.Mcp.Tools.Deploy/src/Services/DeployService.cs index dc89e69a22..8a82ea1108 100644 --- a/tools/Azure.Mcp.Tools.Deploy/src/Services/DeployService.cs +++ b/tools/Azure.Mcp.Tools.Deploy/src/Services/DeployService.cs @@ -2,9 +2,13 @@ // Licensed under the MIT License. using Azure.Core; +using Azure.Core.Pipeline; using Azure.Mcp.Core.Services.Azure; using Azure.Mcp.Core.Services.Azure.Tenant; using Azure.Mcp.Tools.Deploy.Services.Util; +using Azure.Monitor.Query; +using Azure.Monitor.Query.Logs; +using Azure.ResourceManager; namespace Azure.Mcp.Tools.Deploy.Services; @@ -17,13 +21,24 @@ public async Task GetAzdResourceLogsAsync( int? limit = null, CancellationToken cancellationToken = default) { - TokenCredential credential = await GetCredential(cancellationToken); + var armClient = await CreateArmClientAsync(cancellationToken: cancellationToken); + var logsQueryClient = await CreateLogsQueryClientAsync(cancellationToken); + string result = await AzdResourceLogService.GetAzdResourceLogsAsync( - credential, + armClient, + logsQueryClient, workspaceFolder, azdEnvName, subscriptionId, limit); return result; } + + private async Task CreateLogsQueryClientAsync(CancellationToken cancellationToken) + { + var credential = await GetCredential(cancellationToken); + var options = AddDefaultPolicies(new LogsQueryClientOptions()); + options.Transport = new HttpClientTransport(TenantService.GetClient()); + return new LogsQueryClient(credential, options); + } } diff --git a/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdAppLogRetriever.cs b/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdAppLogRetriever.cs index bf9b5ae693..bd980b05c4 100644 --- a/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdAppLogRetriever.cs +++ b/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdAppLogRetriever.cs @@ -1,4 +1,3 @@ -using Azure.Core; using Azure.Monitor.Query.Logs; using Azure.Monitor.Query.Logs.Models; using Azure.ResourceManager; @@ -8,7 +7,7 @@ namespace Azure.Mcp.Tools.Deploy.Services.Util; -public class AzdAppLogRetriever(TokenCredential credential, string subscriptionId, string azdEnvName) +public class AzdAppLogRetriever(ArmClient armClient, LogsQueryClient logsQueryClient, string subscriptionId, string azdEnvName) { private readonly string _subscriptionId = subscriptionId; private readonly string _azdEnvName = azdEnvName; @@ -17,14 +16,11 @@ public class AzdAppLogRetriever(TokenCredential credential, string subscriptionI private readonly List _logAnalyticsWorkspaceIds = new(); private string _resourceGroupName = string.Empty; - private ArmClient? _armClient; - private LogsQueryClient? _queryClient; + private readonly ArmClient _armClient = armClient ?? throw new ArgumentNullException(nameof(armClient)); + private readonly LogsQueryClient _queryClient = logsQueryClient ?? throw new ArgumentNullException(nameof(logsQueryClient)); public async Task InitializeAsync() { - _armClient = new ArmClient(credential, _subscriptionId); - _queryClient = new LogsQueryClient(credential); - _resourceGroupName = await GetResourceGroupNameAsync(); if (string.IsNullOrEmpty(_resourceGroupName)) { @@ -34,7 +30,7 @@ public async Task InitializeAsync() public async Task GetLogAnalyticsWorkspacesInfoAsync() { - var subscription = _armClient!.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}")); + var subscription = _armClient.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}")); var resourceGroup = await subscription.GetResourceGroupAsync(_resourceGroupName); var filter = "resourceType eq 'Microsoft.OperationalInsights/workspaces'"; @@ -52,7 +48,7 @@ public async Task GetLogAnalyticsWorkspacesInfoAsync() public async Task RegisterAppAsync(ResourceType resourceType, string serviceName) { - var subscription = _armClient!.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}")); + var subscription = _armClient.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}")); var resourceGroup = await subscription.GetResourceGroupAsync(_resourceGroupName); var filter = $"tagName eq 'azd-service-name' and tagValue eq '{serviceName}'"; @@ -107,7 +103,7 @@ public async Task QueryAppLogsAsync(ResourceType resourceType, string se case ResourceType.ContainerApps: logSearchQuery = GetContainerAppLogsQuery(app.Data.Name, actualLimit); // Get last deployment time for container apps - var containerAppResource = _armClient!.GetContainerAppResource(app.Id); + var containerAppResource = _armClient.GetContainerAppResource(app.Id); var containerApp = await containerAppResource.GetAsync(); await foreach (var revision in containerApp.Value.GetContainerAppRevisions()) @@ -123,7 +119,7 @@ public async Task QueryAppLogsAsync(ResourceType resourceType, string se case ResourceType.AppService: case ResourceType.FunctionApp: - var webSiteResource = _armClient!.GetWebSiteResource(app.Id); + var webSiteResource = _armClient.GetWebSiteResource(app.Id); await foreach (var deployment in webSiteResource.GetSiteDeployments()) { @@ -156,7 +152,7 @@ public async Task QueryAppLogsAsync(ResourceType resourceType, string se try { var timeRange = new LogsQueryTimeRange(startTime, endTime); - var response = await _queryClient!.QueryResourceAsync(new(logAnalyticsId), logSearchQuery, timeRange); + var response = await _queryClient.QueryResourceAsync(new(logAnalyticsId), logSearchQuery, timeRange); if (response.Value.Status == LogsQueryResultStatus.Success) { @@ -187,7 +183,7 @@ public async Task QueryAppLogsAsync(ResourceType resourceType, string se private async Task GetResourceGroupNameAsync() { - var subscription = _armClient!.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}")); + var subscription = _armClient.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}")); await foreach (var resourceGroup in subscription.GetResourceGroups()) { diff --git a/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdResourceLogService.cs b/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdResourceLogService.cs index 8d8637e4fb..0f68675fe8 100644 --- a/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdResourceLogService.cs +++ b/tools/Azure.Mcp.Tools.Deploy/src/Services/Util/AzdResourceLogService.cs @@ -1,4 +1,6 @@ -using Azure.Core; +using Azure.Monitor.Query; +using Azure.Monitor.Query.Logs; +using Azure.ResourceManager; using YamlDotNet.Core; using YamlDotNet.Core.Events; @@ -9,7 +11,8 @@ public static class AzdResourceLogService private const string AzureYamlFileName = "azure.yaml"; public static async Task GetAzdResourceLogsAsync( - TokenCredential credential, + ArmClient armClient, + LogsQueryClient logsQueryClient, string workspaceFolder, string azdEnvName, string subscriptionId, @@ -20,7 +23,7 @@ public static async Task GetAzdResourceLogsAsync( try { - var azdAppLogRetriever = new AzdAppLogRetriever(credential, subscriptionId, azdEnvName); + var azdAppLogRetriever = new AzdAppLogRetriever(armClient, logsQueryClient, subscriptionId, azdEnvName); await azdAppLogRetriever.InitializeAsync(); await azdAppLogRetriever.GetLogAnalyticsWorkspacesInfoAsync(); diff --git a/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/DeployCommandTests.cs b/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/DeployCommandTests.cs index 8560792feb..c1b73ce2bf 100644 --- a/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/DeployCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/DeployCommandTests.cs @@ -9,7 +9,7 @@ namespace Azure.Mcp.Tools.Deploy.LiveTests; -public class DeployCommandTests(ITestOutputHelper output) : CommandTestsBase(output) +public class DeployCommandTests(ITestOutputHelper output, TestProxyFixture fixture) : RecordedCommandTestsBase(output, fixture) { private string _subscriptionId = default!; diff --git a/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/assets.json b/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/assets.json new file mode 100644 index 0000000000..6cd66dc42d --- /dev/null +++ b/tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.LiveTests/assets.json @@ -0,0 +1,6 @@ +{ + "AssetsRepo": "Azure/azure-sdk-assets", + "AssetsRepoPrefixPath": "", + "TagPrefix": "Azure.Mcp.Tools.Deploy.LiveTests", + "Tag": "Azure.Mcp.Tools.Deploy.LiveTests_b69f975591" +}