Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.
Closed
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ obj/
.vs/
TestResults/
*.binlog
.vscode/mcp.json

node_modules/
.npmrc

.env
.env.local
.env.*.local
.env.*.local
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = accounts?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new AccountListCommandResult(accounts),
AppConfigJsonContext.Default.AccountListCommandResult) :
null;
AppConfigJsonContext.Default.AccountListCommandResult);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = settings?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new KeyValueListCommandResult(settings),
AppConfigJsonContext.Default.KeyValueListCommandResult) :
null;
AppConfigJsonContext.Default.KeyValueListCommandResult);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = assignments?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new RoleAssignmentListCommandResult(assignments),
AuthorizationJsonContext.Default.RoleAssignmentListCommandResult) :
null;
AuthorizationJsonContext.Default.RoleAssignmentListCommandResult);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,67 +24,71 @@ public class RoleAssignmentListCommandTests
private readonly IServiceProvider _serviceProvider;
private readonly IAuthorizationService _authorizationService;
private readonly ILogger<RoleAssignmentListCommand> _logger;
private readonly RoleAssignmentListCommand _command;
private readonly CommandContext _context;
private readonly Parser _parser;
private readonly string _knownSubscriptionId = "00000000-0000-0000-0000-000000000001";
private readonly string _knownScope = "/subscriptions/00000000-0000-0000-0000-000000000001/resourceGroups/rg1";

public RoleAssignmentListCommandTests()
{
_authorizationService = Substitute.For<IAuthorizationService>();
_logger = Substitute.For<ILogger<RoleAssignmentListCommand>>();

var collection = new ServiceCollection();
collection.AddSingleton(_authorizationService);
var collection = new ServiceCollection().AddSingleton(_authorizationService);

_serviceProvider = collection.BuildServiceProvider();
_command = new(_logger);
_context = new(_serviceProvider);
_parser = new(_command.GetCommand());
}

[Fact]
public async Task ExecuteAsync_ReturnsRoleAssignments_WhenRoleAssignmentsExist()
{
// Arrange
var subscriptionId = "00000000-0000-0000-0000-000000000001";
var scope = $"/subscriptions/{subscriptionId}/resourceGroups/rg1";
var id1 = "00000000-0000-0000-0000-000000000001";
var id2 = "00000000-0000-0000-0000-000000000002";
var expectedRoleAssignments = new List<RoleAssignment>
{
new RoleAssignment
{
Id = $"/subscriptions/{subscriptionId}/resourcegroups/azure-mcp/providers/Microsoft.Authorization/roleAssignments/{id1}",
Id = $"/subscriptions/{_knownSubscriptionId}/resourcegroups/azure-mcp/providers/Microsoft.Authorization/roleAssignments/{id1}",
Name = "Test role definition 1",
PrincipalId = new Guid(id1),
PrincipalType = "User",
RoleDefinitionId = $"/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/{id1}",
Scope = scope,
RoleDefinitionId = $"/subscriptions/{_knownSubscriptionId}/providers/Microsoft.Authorization/roleDefinitions/{id1}",
Scope = _knownScope,
Description = "Role assignment for azmcp test 1",
DelegatedManagedIdentityResourceId = string.Empty,
Condition = string.Empty
},
new RoleAssignment
{
Id = $"/subscriptions/{subscriptionId}/resourcegroups/azure-mcp/providers/Microsoft.Authorization/roleAssignments/{id2}",
Id = $"/subscriptions/{_knownSubscriptionId}/resourcegroups/azure-mcp/providers/Microsoft.Authorization/roleAssignments/{id2}",
Name = "Test role definition 2",
PrincipalId = new Guid(id2),
PrincipalType = "User",
RoleDefinitionId = $"/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/{id2}",
Scope = scope,
RoleDefinitionId = $"/subscriptions/{_knownSubscriptionId}/providers/Microsoft.Authorization/roleDefinitions/{id2}",
Scope = _knownScope,
Description = "Role assignment for azmcp test 2",
DelegatedManagedIdentityResourceId = string.Empty,
Condition = "ActionMatches{'Microsoft.Authorization/roleAssignments/write'}"
}
};
_authorizationService.ListRoleAssignments(
Arg.Is(scope),
Arg.Is(_knownScope),
Arg.Any<string>(),
Arg.Any<RetryPolicyOptions>())
.Returns(expectedRoleAssignments);
var command = new RoleAssignmentListCommand(_logger);
var args = command.GetCommand().Parse([
"--subscription", subscriptionId,
"--scope", scope,

var args = _parser.Parse([
"--subscription", _knownSubscriptionId,
"--scope", _knownScope,
]);
var context = new CommandContext(_serviceProvider);

// Act
var response = await command.ExecuteAsync(context, args);
var response = await _command.ExecuteAsync(_context, args);

// Assert
Assert.NotNull(response);
Expand All @@ -98,49 +102,48 @@ public async Task ExecuteAsync_ReturnsRoleAssignments_WhenRoleAssignmentsExist()
}

[Fact]
public async Task ExecuteAsync_ReturnsNull_WhenNoRoleAssignments()
public async Task ExecuteAsync_ReturnsEmptyList_WhenNoRoleAssignments()
{
// Arrange
var subscriptionId = "00000000-0000-0000-0000-000000000001";
var scope = $"/subscriptions/{subscriptionId}/resourceGroups/rg1";
_authorizationService.ListRoleAssignments(scope, null, null)
_authorizationService.ListRoleAssignments(Arg.Is(_knownScope), Arg.Any<string>(), Arg.Any<RetryPolicyOptions>())
.Returns([]);

var command = new RoleAssignmentListCommand(_logger);
var args = command.GetCommand().Parse([
"--subscription", subscriptionId,
"--scope", scope
var args = _parser.Parse([
"--subscription", _knownSubscriptionId,
"--scope", _knownScope
]);
var context = new CommandContext(_serviceProvider);

// Act
var response = await command.ExecuteAsync(context, args);
var response = await _command.ExecuteAsync(_context, args);

// Assert
Assert.NotNull(response);
Assert.Null(response.Results);
Assert.NotNull(response.Results);

var json = JsonSerializer.Serialize(response.Results);
var result = JsonSerializer.Deserialize<RoleAssignmentListResult>(json);

Assert.NotNull(result);
Assert.NotNull(result.Assignments);
Assert.Empty(result.Assignments);
}

[Fact]
public async Task ExecuteAsync_HandlesException()
{
// Arrange
var expectedError = "Test error";
var subscriptionId = "00000000-0000-0000-0000-000000000001";
var scope = $"/subscriptions/{subscriptionId}/resourceGroups/rg1";

_authorizationService.ListRoleAssignments(scope, null, Arg.Any<RetryPolicyOptions>())
_authorizationService.ListRoleAssignments(Arg.Is(_knownScope), Arg.Any<string>(), Arg.Any<RetryPolicyOptions>())
.ThrowsAsync(new Exception(expectedError));

var command = new RoleAssignmentListCommand(_logger);
var args = command.GetCommand().Parse([
"--subscription", subscriptionId,
"--scope", scope
var args = _parser.Parse([
"--subscription", _knownSubscriptionId,
"--scope", _knownScope
]);
var context = new CommandContext(_serviceProvider);

// Act
var response = await command.ExecuteAsync(context, args);
var response = await _command.ExecuteAsync(_context, args);

// Assert
Assert.NotNull(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = accounts?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new AccountListCommandResult(accounts),
CosmosJsonContext.Default.AccountListCommandResult) :
null;
CosmosJsonContext.Default.AccountListCommandResult);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = containers?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new ContainerListCommandResult(containers),
CosmosJsonContext.Default.ContainerListCommandResult) :
null;
CosmosJsonContext.Default.ContainerListCommandResult);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = databases?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new DatabaseListCommandResult(databases),
CosmosJsonContext.Default.DatabaseListCommandResult) :
null;
CosmosJsonContext.Default.DatabaseListCommandResult);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,36 @@ public class AccountListCommandTests
private readonly IServiceProvider _serviceProvider;
private readonly ICosmosService _cosmosService;
private readonly ILogger<AccountListCommand> _logger;
private readonly AccountListCommand _command;
private readonly CommandContext _context;
private readonly Parser _parser;
private readonly string _knownSubscriptionId = "00000000-0000-0000-0000-000000000001";

public AccountListCommandTests()
{
_cosmosService = Substitute.For<ICosmosService>();
_logger = Substitute.For<ILogger<AccountListCommand>>();

var collection = new ServiceCollection();
collection.AddSingleton(_cosmosService);
var collection = new ServiceCollection().AddSingleton(_cosmosService);

_serviceProvider = collection.BuildServiceProvider();
_command = new(_logger);
_context = new(_serviceProvider);
_parser = new(_command.GetCommand());
}

[Fact]
public async Task ExecuteAsync_ReturnsAccounts_WhenAccountsExist()
{
// Arrange
var expectedAccounts = new List<string> { "account1", "account2" };
_cosmosService.GetCosmosAccounts(Arg.Is("sub123"), Arg.Any<string>(), Arg.Any<RetryPolicyOptions>())
_cosmosService.GetCosmosAccounts(Arg.Is(_knownSubscriptionId), Arg.Any<string>(), Arg.Any<RetryPolicyOptions>())
.Returns(expectedAccounts);

var command = new AccountListCommand(_logger);
var args = command.GetCommand().Parse(["--subscription", "sub123"]);
var context = new CommandContext(_serviceProvider);
var args = _parser.Parse(["--subscription", _knownSubscriptionId]);

// Act
var response = await command.ExecuteAsync(context, args);
var response = await _command.ExecuteAsync(_context, args);

// Assert
Assert.NotNull(response);
Expand All @@ -62,40 +66,42 @@ public async Task ExecuteAsync_ReturnsAccounts_WhenAccountsExist()
}

[Fact]
public async Task ExecuteAsync_ReturnsNull_WhenNoAccounts()
public async Task ExecuteAsync_ReturnsEmptyList_WhenNoAccounts()
{
// Arrange
_cosmosService.GetCosmosAccounts("sub123", null, null)
_cosmosService.GetCosmosAccounts(Arg.Is(_knownSubscriptionId), Arg.Any<string>(), Arg.Any<RetryPolicyOptions>())
.Returns([]);

var command = new AccountListCommand(_logger);
var args = command.GetCommand().Parse(["--subscription", "sub123"]);
var context = new CommandContext(_serviceProvider);
var args = _parser.Parse(["--subscription", _knownSubscriptionId]);

// Act
var response = await command.ExecuteAsync(context, args);
var response = await _command.ExecuteAsync(_context, args);

// Assert
Assert.NotNull(response);
Assert.Null(response.Results);
Assert.NotNull(response.Results);

var json = JsonSerializer.Serialize(response.Results);
var result = JsonSerializer.Deserialize<AccountListResult>(json);

Assert.NotNull(result);
Assert.NotNull(result.Accounts);
Assert.Empty(result.Accounts);
}

[Fact]
public async Task ExecuteAsync_HandlesException()
{
// Arrange
var expectedError = "Test error";
var subscriptionId = "sub123";

_cosmosService.GetCosmosAccounts(subscriptionId, null, Arg.Any<RetryPolicyOptions>())
_cosmosService.GetCosmosAccounts(Arg.Is(_knownSubscriptionId), Arg.Any<string>(), Arg.Any<RetryPolicyOptions>())
.ThrowsAsync(new Exception(expectedError));

var command = new AccountListCommand(_logger);
var args = command.GetCommand().Parse(["--subscription", subscriptionId]);
var context = new CommandContext(_serviceProvider);
var args = _parser.Parse(["--subscription", _knownSubscriptionId]);

// Act
var response = await command.ExecuteAsync(context, args);
var response = await _command.ExecuteAsync(_context, args);

// Assert
Assert.NotNull(response);
Expand All @@ -108,4 +114,4 @@ private class AccountListResult
[JsonPropertyName("accounts")]
public List<string> Accounts { get; set; } = [];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,9 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Tenant,
options.RetryPolicy);

context.Response.Results = keys?.Count > 0 ?
ResponseResult.Create(
context.Response.Results = ResponseResult.Create(
new KeyListCommandResult(keys),
KeyVaultJsonContext.Default.KeyListCommandResult) :
null;
KeyVaultJsonContext.Default.KeyListCommandResult);
}
catch (Exception ex)
{
Expand Down
Loading
Loading