From 8925d975b18109279de68632fb72ad44712f8e85 Mon Sep 17 00:00:00 2001 From: Giulio Vian Date: Sat, 18 Jul 2020 15:45:00 +0100 Subject: [PATCH] Giuliov/issue 142 (#143) * first attempt * fix test * Check if mapping was deleted (#142) * review exit codes --- src/aggregator-cli/CommandBase.cs | 13 ++++++----- src/aggregator-cli/ExitCodes.cs | 15 +++++++++++++ .../Instances/ConfigureInstanceCommand.cs | 12 +++++----- .../Instances/InstallInstanceCommand.cs | 6 ++--- .../Instances/ListInstancesCommand.cs | 12 +++++----- .../Instances/StreamLogsCommand.cs | 2 +- .../Instances/UninstallInstanceCommand.cs | 2 +- .../Instances/UpdateInstance.cs | 2 +- src/aggregator-cli/Logon/LogonAzureCommand.cs | 6 ++--- .../Logon/LogonDevOpsCommand.cs | 4 ++-- .../Mappings/AggregatorMappings.cs | 19 +++++++++++----- .../Mappings/ListMappingsCommand.cs | 8 +++++-- src/aggregator-cli/Mappings/MapRuleCommand.cs | 4 ++-- .../Mappings/UnmapRuleCommand.cs | 19 ++++++++++++---- src/aggregator-cli/Program.cs | 4 ++-- src/aggregator-cli/Rules/AddRuleCommand.cs | 2 +- .../Rules/ConfigureRuleCommand.cs | 2 +- src/aggregator-cli/Rules/InvokeRuleCommand.cs | 4 ++-- src/aggregator-cli/Rules/ListRulesCommand.cs | 7 ++++-- src/aggregator-cli/Rules/RemoveRuleCommand.cs | 8 ++++--- src/aggregator-cli/Rules/UpdateRuleCommand.cs | 2 +- .../TestCommands/CleanupTestCommand.cs | 2 +- .../Scenario3_MultiInstance.cs | 22 ++++++++++++++----- 23 files changed, 119 insertions(+), 58 deletions(-) create mode 100644 src/aggregator-cli/ExitCodes.cs diff --git a/src/aggregator-cli/CommandBase.cs b/src/aggregator-cli/CommandBase.cs index 225cc79b..52c42154 100644 --- a/src/aggregator-cli/CommandBase.cs +++ b/src/aggregator-cli/CommandBase.cs @@ -43,15 +43,18 @@ internal int Run(CancellationToken cancellationToken) t.Wait(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); int rc = t.Result; - if (rc != 0) + if (rc == ExitCodes.Success) { - Logger.WriteError("Failed!"); + Logger.WriteSuccess("Succeeded"); + } + else if (rc == ExitCodes.NotFound) + { + Logger.WriteWarning("Not found"); } else { - Logger.WriteSuccess("Succeeded"); + Logger.WriteError("Failed!"); } - return rc; } catch (Exception ex) @@ -61,7 +64,7 @@ internal int Run(CancellationToken cancellationToken) ? ex.Message : ex.InnerException.Message ); - return 99; + return ExitCodes.Unexpected; } } diff --git a/src/aggregator-cli/ExitCodes.cs b/src/aggregator-cli/ExitCodes.cs new file mode 100644 index 00000000..f793c09d --- /dev/null +++ b/src/aggregator-cli/ExitCodes.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace aggregator.cli +{ + internal static class ExitCodes + { + public const int Success = 0; + public const int Failure = 1; + public const int InvalidArguments = 2; + public const int NotFound = 3; + public const int Unexpected = 99; + } +} diff --git a/src/aggregator-cli/Instances/ConfigureInstanceCommand.cs b/src/aggregator-cli/Instances/ConfigureInstanceCommand.cs index c84aa1bc..dd8c1d27 100644 --- a/src/aggregator-cli/Instances/ConfigureInstanceCommand.cs +++ b/src/aggregator-cli/Instances/ConfigureInstanceCommand.cs @@ -36,16 +36,16 @@ internal override async Task RunAsync(CancellationToken cancellationToken) .BuildAsync(cancellationToken); var instances = new AggregatorInstances(context.Azure, context.Logger, context.Naming); var instance = context.Naming.Instance(Name, ResourceGroup); - bool ok = false; if (Authentication) { - ok = await instances.ChangeAppSettingsAsync(instance, Location, SaveMode, cancellationToken); - } else + bool ok = await instances.ChangeAppSettingsAsync(instance, Location, SaveMode, cancellationToken); + return ok ? ExitCodes.Success : ExitCodes.Failure; + } + else { context.Logger.WriteError($"Unsupported command option(s)"); + return ExitCodes.InvalidArguments; } - - return ok ? 0 : 1; } } -} \ No newline at end of file +} diff --git a/src/aggregator-cli/Instances/InstallInstanceCommand.cs b/src/aggregator-cli/Instances/InstallInstanceCommand.cs index 1ce69c4b..89d498ee 100644 --- a/src/aggregator-cli/Instances/InstallInstanceCommand.cs +++ b/src/aggregator-cli/Instances/InstallInstanceCommand.cs @@ -44,12 +44,12 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (!validHostingPlanSkus.Contains(HostingPlanSku)) { Logger.WriteError($"Invalid value for hostingPlanSku: must be one of {String.Join(",", validHostingPlanSkus)}"); - return 2; + return ExitCodes.InvalidArguments; } if (!validHostingPlanTiers.Contains(HostingPlanTier)) { Logger.WriteError($"Invalid value for hostingPlanTier: must be one of {String.Join(",", validHostingPlanTiers)}"); - return 2; + return ExitCodes.InvalidArguments; } var tuning = new AggregatorInstances.InstanceFineTuning { @@ -65,7 +65,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instances = new AggregatorInstances(context.Azure, context.Logger, context.Naming); var instance = context.Naming.GetInstanceCreateNames(Name, ResourceGroup); bool ok = await instances.AddAsync(instance, Location, RequiredVersion, SourceUrl, tuning, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Instances/ListInstancesCommand.cs b/src/aggregator-cli/Instances/ListInstancesCommand.cs index a0f94ca9..6ea5670f 100644 --- a/src/aggregator-cli/Instances/ListInstancesCommand.cs +++ b/src/aggregator-cli/Instances/ListInstancesCommand.cs @@ -50,7 +50,7 @@ private async Task ListByLocationAsync(CommandContext context, AggregatorIn { context.Logger.WriteInfo($"No aggregator instances found in {Location} Region."); } - return 0; + return ExitCodes.Success; } private async Task ListInResourceGroupAsync(CommandContext context, AggregatorInstances instances, CancellationToken cancellationToken) @@ -68,7 +68,7 @@ private async Task ListInResourceGroupAsync(CommandContext context, Aggrega context.Logger.WriteInfo($"No aggregator instances found in {ResourceGroup} Resource Group."); } - return 0; + return ExitCodes.Success; } private static async Task ListAllAsync(CommandContext context, AggregatorInstances instances, CancellationToken cancellationToken) @@ -80,13 +80,15 @@ private static async Task ListAllAsync(CommandContext context, AggregatorIn context.Logger.WriteOutput(dataObject); any = true; } - if (!any) { context.Logger.WriteInfo("No aggregator instances found."); + return ExitCodes.NotFound; + } + else + { + return ExitCodes.Success; } - - return 0; } } } diff --git a/src/aggregator-cli/Instances/StreamLogsCommand.cs b/src/aggregator-cli/Instances/StreamLogsCommand.cs index a9c88186..82de25ca 100644 --- a/src/aggregator-cli/Instances/StreamLogsCommand.cs +++ b/src/aggregator-cli/Instances/StreamLogsCommand.cs @@ -24,7 +24,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instance = context.Naming.Instance(Instance, ResourceGroup); var instances = new AggregatorInstances(context.Azure, context.Logger, context.Naming); bool ok = await instances.StreamLogsAsync(instance, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Instances/UninstallInstanceCommand.cs b/src/aggregator-cli/Instances/UninstallInstanceCommand.cs index 5c2130ed..2776091c 100644 --- a/src/aggregator-cli/Instances/UninstallInstanceCommand.cs +++ b/src/aggregator-cli/Instances/UninstallInstanceCommand.cs @@ -39,7 +39,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instances = new AggregatorInstances(context.Azure, context.Logger, context.Naming); var ok = await instances.RemoveAsync(instance, Location); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Instances/UpdateInstance.cs b/src/aggregator-cli/Instances/UpdateInstance.cs index b39a00ee..77567fa6 100644 --- a/src/aggregator-cli/Instances/UpdateInstance.cs +++ b/src/aggregator-cli/Instances/UpdateInstance.cs @@ -32,7 +32,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instance = context.Naming.Instance(Instance, ResourceGroup); bool ok = await instances.UpdateAsync(instance, RequiredVersion, SourceUrl, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Logon/LogonAzureCommand.cs b/src/aggregator-cli/Logon/LogonAzureCommand.cs index c1327d90..5e623cb0 100644 --- a/src/aggregator-cli/Logon/LogonAzureCommand.cs +++ b/src/aggregator-cli/Logon/LogonAzureCommand.cs @@ -36,7 +36,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (azure == null) { context.Logger.WriteError("Invalid azure credentials"); - return 2; + return ExitCodes.InvalidArguments; } // FIX #60: call some read API to validate parameters try @@ -48,9 +48,9 @@ internal override async Task RunAsync(CancellationToken cancellationToken) int nl = ex.Message.IndexOf(Environment.NewLine); string m = nl != -1 ? ex.Message.Remove(nl) : ex.Message; context.Logger.WriteError("Invalid azure credentials: " + m); - return 2; + return ExitCodes.InvalidArguments; } - return 0; + return ExitCodes.Success; } } } diff --git a/src/aggregator-cli/Logon/LogonDevOpsCommand.cs b/src/aggregator-cli/Logon/LogonDevOpsCommand.cs index d9df004e..57b878f6 100644 --- a/src/aggregator-cli/Logon/LogonDevOpsCommand.cs +++ b/src/aggregator-cli/Logon/LogonDevOpsCommand.cs @@ -36,10 +36,10 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (devops == null) { context.Logger.WriteError("Invalid Azure DevOps credentials"); - return 2; + return ExitCodes.InvalidArguments; } - return 0; + return ExitCodes.Success; } } } diff --git a/src/aggregator-cli/Mappings/AggregatorMappings.cs b/src/aggregator-cli/Mappings/AggregatorMappings.cs index 094227aa..fa240f2b 100644 --- a/src/aggregator-cli/Mappings/AggregatorMappings.cs +++ b/src/aggregator-cli/Mappings/AggregatorMappings.cs @@ -12,6 +12,13 @@ namespace aggregator.cli { + internal enum RemoveOutcome + { + Succeeded = 0, + NotFound = 2, + Failed = 1 + } + internal class AggregatorMappings { private readonly VssConnection devops; @@ -157,17 +164,17 @@ internal async Task AddAsync(string projectName, string @event, EventFilte return newSubscription.Id; } - internal async Task RemoveInstanceAsync(InstanceName instance) + internal async Task RemoveInstanceAsync(InstanceName instance) { return await RemoveRuleEventAsync("*", instance, "*", "*"); } - internal async Task RemoveRuleAsync(InstanceName instance, string rule) + internal async Task RemoveRuleAsync(InstanceName instance, string rule) { return await RemoveRuleEventAsync("*", instance, "*", rule); } - internal async Task RemoveRuleEventAsync(string @event, InstanceName instance, string projectName, string rule) + internal async Task RemoveRuleEventAsync(string @event, InstanceName instance, string projectName, string rule) { logger.WriteInfo($"Querying the Azure DevOps subscriptions for rule(s) {instance.PlainName}/{rule}"); var serviceHooksClient = devops.GetClient(); @@ -200,14 +207,16 @@ internal async Task RemoveRuleEventAsync(string @event, InstanceName insta .StartsWith(invocationUrl, StringComparison.OrdinalIgnoreCase)); } + uint count = 0; foreach (var ruleSub in ruleSubs) { logger.WriteVerbose($"Deleting subscription {ruleSub.EventDescription} {ruleSub.EventType}..."); await serviceHooksClient.DeleteSubscriptionAsync(ruleSub.Id); logger.WriteInfo($"Subscription {ruleSub.EventDescription} {ruleSub.EventType} deleted."); + count++; } - return true; + return count > 0 ? RemoveOutcome.Succeeded : RemoveOutcome.NotFound; } } @@ -261,4 +270,4 @@ public static IEnumerable ToFilterConditions(this EventFil }); } } -} \ No newline at end of file +} diff --git a/src/aggregator-cli/Mappings/ListMappingsCommand.cs b/src/aggregator-cli/Mappings/ListMappingsCommand.cs index a01c381e..acb9f29e 100644 --- a/src/aggregator-cli/Mappings/ListMappingsCommand.cs +++ b/src/aggregator-cli/Mappings/ListMappingsCommand.cs @@ -29,7 +29,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) && string.IsNullOrEmpty(Project)) { context.Logger.WriteError("Specify at least one filtering parameter."); - return 2; + return ExitCodes.InvalidArguments; } var instance = string.IsNullOrEmpty(Instance) ? null : context.Naming.Instance(Instance, ResourceGroup); // HACK we pass null as the next calls do not use the Azure connection @@ -44,8 +44,12 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (!any) { context.Logger.WriteInfo("No rule mappings found."); + return ExitCodes.NotFound; + } + else + { + return ExitCodes.Success; } - return 0; } } } diff --git a/src/aggregator-cli/Mappings/MapRuleCommand.cs b/src/aggregator-cli/Mappings/MapRuleCommand.cs index 9abf0194..0d2ef748 100644 --- a/src/aggregator-cli/Mappings/MapRuleCommand.cs +++ b/src/aggregator-cli/Mappings/MapRuleCommand.cs @@ -49,7 +49,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (!ok) { context.Logger.WriteError($"Invalid event type."); - return 2; + return ExitCodes.InvalidArguments; } var filters = new EventFilters @@ -62,7 +62,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instance = context.Naming.Instance(Instance, ResourceGroup); var id = await mappings.AddAsync(Project, Event, filters, instance, Rule, ImpersonateExecution, cancellationToken); - return id.Equals(Guid.Empty) ? 1 : 0; + return id.Equals(Guid.Empty) ? ExitCodes.Failure : ExitCodes.Success; } } } diff --git a/src/aggregator-cli/Mappings/UnmapRuleCommand.cs b/src/aggregator-cli/Mappings/UnmapRuleCommand.cs index 268f19ff..63e0bb1e 100644 --- a/src/aggregator-cli/Mappings/UnmapRuleCommand.cs +++ b/src/aggregator-cli/Mappings/UnmapRuleCommand.cs @@ -31,16 +31,27 @@ internal override async Task RunAsync(CancellationToken cancellationToken) .WithAzureLogon() .WithDevOpsLogon() .BuildAsync(cancellationToken); - bool ok = DevOpsEvents.IsValidEvent(Event); + bool ok = DevOpsEvents.IsValidEvent(Event) || Event == "*"; if (!ok) { context.Logger.WriteError($"Invalid event type."); - return 2; + return ExitCodes.InvalidArguments; } var instance = context.Naming.Instance(Instance, ResourceGroup); var mappings = new AggregatorMappings(context.Devops, context.Azure, context.Logger, context.Naming); - ok = await mappings.RemoveRuleEventAsync(Event, instance, Project, Rule); - return ok ? 0 : 1; + var outcome = await mappings.RemoveRuleEventAsync(Event, instance, Project, Rule); + switch (outcome) + { + case RemoveOutcome.Succeeded: + return ExitCodes.Success; + case RemoveOutcome.NotFound: + context.Logger.WriteWarning($"No mapping(s) found for rule(s) {instance.PlainName}/{Rule}"); + return ExitCodes.NotFound; + case RemoveOutcome.Failed: + return ExitCodes.Failure; + default: + return ExitCodes.Unexpected; + } } } } diff --git a/src/aggregator-cli/Program.cs b/src/aggregator-cli/Program.cs index 27bd5051..bd2e179f 100644 --- a/src/aggregator-cli/Program.cs +++ b/src/aggregator-cli/Program.cs @@ -70,7 +70,7 @@ void cancelEventHandler(object sender, ConsoleCancelEventArgs e) typeof(ListMappingsCommand), typeof(MapRuleCommand), typeof(UnmapRuleCommand) }; var parserResult = parser.ParseArguments(args, types); - int rc = -1; + int rc = ExitCodes.Unexpected; var cancellationToken = cancellationTokenSource.Token; parserResult .WithParsed(cmd => rc = cmd.Run(cancellationToken)) @@ -96,7 +96,7 @@ void cancelEventHandler(object sender, ConsoleCancelEventArgs e) { var helpText = HelpText.AutoBuild(parserResult); Console.Error.Write(helpText); - rc = 1; + rc = ExitCodes.InvalidArguments; }); Console.ForegroundColor = save; diff --git a/src/aggregator-cli/Rules/AddRuleCommand.cs b/src/aggregator-cli/Rules/AddRuleCommand.cs index f0bf30e3..1c0e9f24 100644 --- a/src/aggregator-cli/Rules/AddRuleCommand.cs +++ b/src/aggregator-cli/Rules/AddRuleCommand.cs @@ -30,7 +30,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instance = context.Naming.Instance(Instance, ResourceGroup); var rules = new AggregatorRules(context.Azure, context.Logger); bool ok = await rules.AddAsync(instance, Name, File, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Rules/ConfigureRuleCommand.cs b/src/aggregator-cli/Rules/ConfigureRuleCommand.cs index f33320e0..9f32263b 100644 --- a/src/aggregator-cli/Rules/ConfigureRuleCommand.cs +++ b/src/aggregator-cli/Rules/ConfigureRuleCommand.cs @@ -42,7 +42,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var impersonate = GetEnableStatus(DisableImpersonateExecution, EnableImpersonateExecution); var ok = await rules.ConfigureAsync(instance, Name, disable, impersonate, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } diff --git a/src/aggregator-cli/Rules/InvokeRuleCommand.cs b/src/aggregator-cli/Rules/InvokeRuleCommand.cs index 6bec95d2..5ef86e01 100644 --- a/src/aggregator-cli/Rules/InvokeRuleCommand.cs +++ b/src/aggregator-cli/Rules/InvokeRuleCommand.cs @@ -58,14 +58,14 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (Local) { bool ok = await rules.InvokeLocalAsync(Project, Event, WorkItemId, Source, DryRun, SaveMode, ImpersonateExecution, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } else { var instance = context.Naming.Instance(Instance, ResourceGroup); context.Logger.WriteWarning("Untested feature!"); bool ok = await rules.InvokeRemoteAsync(Account, Project, Event, WorkItemId, instance, Name, DryRun, SaveMode, ImpersonateExecution, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Rules/ListRulesCommand.cs b/src/aggregator-cli/Rules/ListRulesCommand.cs index bf896647..cff2de4f 100644 --- a/src/aggregator-cli/Rules/ListRulesCommand.cs +++ b/src/aggregator-cli/Rules/ListRulesCommand.cs @@ -34,9 +34,12 @@ internal override async Task RunAsync(CancellationToken cancellationToken) if (!any) { context.Logger.WriteInfo($"No rules found in aggregator instance {instance.PlainName}."); + return ExitCodes.NotFound; + } + else + { + return ExitCodes.Success; } - - return 0; } } } diff --git a/src/aggregator-cli/Rules/RemoveRuleCommand.cs b/src/aggregator-cli/Rules/RemoveRuleCommand.cs index e4d48b53..926aa84a 100644 --- a/src/aggregator-cli/Rules/RemoveRuleCommand.cs +++ b/src/aggregator-cli/Rules/RemoveRuleCommand.cs @@ -27,12 +27,14 @@ internal override async Task RunAsync(CancellationToken cancellationToken) .BuildAsync(cancellationToken); var instance = context.Naming.Instance(Instance, ResourceGroup); var mappings = new AggregatorMappings(context.Devops, context.Azure, context.Logger, context.Naming); - bool ok = await mappings.RemoveRuleAsync(instance, Name); + var outcome = await mappings.RemoveRuleAsync(instance, Name); + if (outcome == RemoveOutcome.Failed) + return ExitCodes.Failure; var rules = new AggregatorRules(context.Azure, context.Logger); //rules.Progress += Instances_Progress; - ok = ok && await rules.RemoveAsync(instance, Name, cancellationToken); - return ok ? 0 : 1; + bool ok = await rules.RemoveAsync(instance, Name, cancellationToken); + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/Rules/UpdateRuleCommand.cs b/src/aggregator-cli/Rules/UpdateRuleCommand.cs index 7798af50..17783565 100644 --- a/src/aggregator-cli/Rules/UpdateRuleCommand.cs +++ b/src/aggregator-cli/Rules/UpdateRuleCommand.cs @@ -36,7 +36,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) var instance = context.Naming.Instance(Instance, ResourceGroup); var rules = new AggregatorRules(context.Azure, context.Logger); bool ok = await rules.UpdateAsync(instance, Name, File, RequiredVersion, SourceUrl, cancellationToken); - return ok ? 0 : 1; + return ok ? ExitCodes.Success : ExitCodes.Failure; } } } diff --git a/src/aggregator-cli/TestCommands/CleanupTestCommand.cs b/src/aggregator-cli/TestCommands/CleanupTestCommand.cs index b75a785d..7930caf3 100644 --- a/src/aggregator-cli/TestCommands/CleanupTestCommand.cs +++ b/src/aggregator-cli/TestCommands/CleanupTestCommand.cs @@ -44,7 +44,7 @@ internal override async Task RunAsync(CancellationToken cancellationToken) Logger.WriteInfo($"Resources deleted."); - return 0; + return ExitCodes.Success; } } } diff --git a/src/integrationtests-cli/Scenario3_MultiInstance.cs b/src/integrationtests-cli/Scenario3_MultiInstance.cs index c3cd6fcb..f171bcc5 100644 --- a/src/integrationtests-cli/Scenario3_MultiInstance.cs +++ b/src/integrationtests-cli/Scenario3_MultiInstance.cs @@ -1,8 +1,4 @@ -using Microsoft.Azure.Management.Fluent; -using Microsoft.Azure.Management.ResourceManager.Fluent; -using Microsoft.Azure.Management.ResourceManager.Fluent.Core; -using Microsoft.Azure.Management.ResourceManager.Fluent.Models; -using Xunit; +using Xunit; using Xunit.Abstractions; using XUnitPriorityOrderer; @@ -150,9 +146,25 @@ void UnmapRules(string instancePrefix, string rule) Assert.DoesNotContain("] Failed!", output); } + [Theory, Order(904)] + [InlineData("my54", "test5")] + void UnmapUnmappedRule(string instancePrefix, string rule) + { + string instance = instancePrefix + TestLogonData.UniqueSuffix; + (int rc, string output) = RunAggregatorCommand($"unmap.rule --verbose --project \"{TestLogonData.ProjectName}\" --event workitem.created --instance {instance} --resourceGroup {TestLogonData.ResourceGroup} --rule {rule}"); + + Assert.Equal(3, rc); + Assert.Contains("No mapping(s) found for rule(s)", output); + } + [Fact, Order(999)] void FinalCleanUp() { + string instance = "my45" + TestLogonData.UniqueSuffix; + (int _, string _) = RunAggregatorCommand($"unmap.rule --verbose --project \"{TestLogonData.ProjectName}\" --event * --rule * --instance {instance} --resourceGroup {TestLogonData.ResourceGroup}"); + instance = "my54" + TestLogonData.UniqueSuffix; + (int _, string _) = RunAggregatorCommand($"unmap.rule --verbose --project \"{TestLogonData.ProjectName}\" --event * --rule * --instance {instance} --resourceGroup {TestLogonData.ResourceGroup}"); + (int rc, string output) = RunAggregatorCommand($"test.cleanup --verbose --resourceGroup {TestLogonData.ResourceGroup} "); Assert.Equal(0, rc); }