Skip to content
Open
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
19 changes: 17 additions & 2 deletions tools/Azure.Mcp.Tools.Deploy/src/Services/DeployService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -17,13 +21,24 @@ public async Task<string> 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<LogsQueryClient> CreateLogsQueryClientAsync(CancellationToken cancellationToken)
{
var credential = await GetCredential(cancellationToken);
var options = AddDefaultPolicies(new LogsQueryClientOptions());
options.Transport = new HttpClientTransport(TenantService.GetClient());
return new LogsQueryClient(credential, options);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Azure.Core;
using Azure.Monitor.Query.Logs;
using Azure.Monitor.Query.Logs.Models;
using Azure.ResourceManager;
Expand All @@ -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;
Expand All @@ -17,14 +16,11 @@ public class AzdAppLogRetriever(TokenCredential credential, string subscriptionI
private readonly List<string> _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))
{
Expand All @@ -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'";
Expand All @@ -52,7 +48,7 @@ public async Task GetLogAnalyticsWorkspacesInfoAsync()

public async Task<GenericResource> 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}'";
Expand Down Expand Up @@ -107,7 +103,7 @@ public async Task<string> 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())
Expand All @@ -123,7 +119,7 @@ public async Task<string> 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())
{
Expand Down Expand Up @@ -156,7 +152,7 @@ public async Task<string> 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)
{
Expand Down Expand Up @@ -187,7 +183,7 @@ public async Task<string> QueryAppLogsAsync(ResourceType resourceType, string se

private async Task<string> GetResourceGroupNameAsync()
{
var subscription = _armClient!.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}"));
var subscription = _armClient.GetSubscriptionResource(new($"/subscriptions/{_subscriptionId}"));

await foreach (var resourceGroup in subscription.GetResourceGroups())
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -9,7 +11,8 @@ public static class AzdResourceLogService
private const string AzureYamlFileName = "azure.yaml";

public static async Task<string> GetAzdResourceLogsAsync(
TokenCredential credential,
ArmClient armClient,
LogsQueryClient logsQueryClient,
string workspaceFolder,
string azdEnvName,
string subscriptionId,
Expand All @@ -20,7 +23,7 @@ public static async Task<string> GetAzdResourceLogsAsync(

try
{
var azdAppLogRetriever = new AzdAppLogRetriever(credential, subscriptionId, azdEnvName);
var azdAppLogRetriever = new AzdAppLogRetriever(armClient, logsQueryClient, subscriptionId, azdEnvName);
await azdAppLogRetriever.InitializeAsync();
await azdAppLogRetriever.GetLogAnalyticsWorkspacesInfoAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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!;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "",
"TagPrefix": "Azure.Mcp.Tools.Deploy.LiveTests",
"Tag": "Azure.Mcp.Tools.Deploy.LiveTests_b69f975591"
}