diff --git a/util/SeederUtility/Commands/OutputFormat.cs b/util/SeederUtility/Commands/OutputFormat.cs new file mode 100644 index 000000000000..b23ea97d276b --- /dev/null +++ b/util/SeederUtility/Commands/OutputFormat.cs @@ -0,0 +1,7 @@ +namespace Bit.SeederUtility.Commands; + +public enum OutputFormat +{ + Text, + Json, +} diff --git a/util/SeederUtility/Commands/PresetArgs.cs b/util/SeederUtility/Commands/PresetArgs.cs index d9bc8af37ebe..d36051043a38 100644 --- a/util/SeederUtility/Commands/PresetArgs.cs +++ b/util/SeederUtility/Commands/PresetArgs.cs @@ -14,6 +14,14 @@ public class PresetArgs : IArgumentModel [Option('l', "list", Description = "List all available presets and fixtures")] public bool List { get; set; } + [Option("output", Description = "Output format for --list: text or json (default: text)")] + public string? Output { get; set; } + + public OutputFormat GetOutputFormat() => + string.IsNullOrWhiteSpace(Output) + ? OutputFormat.Text + : Enum.Parse(Output, ignoreCase: true); + [Option("mangle", Description = "Enable mangling for test isolation")] public bool Mangle { get; set; } @@ -25,6 +33,12 @@ public class PresetArgs : IArgumentModel public void Validate() { + if (!string.IsNullOrWhiteSpace(Output) + && !Enum.TryParse(Output, ignoreCase: true, out _)) + { + throw new ArgumentException($"Unrecognized output format '{Output}'. Allowed: text, json."); + } + if (List) { return; diff --git a/util/SeederUtility/Commands/PresetCommand.cs b/util/SeederUtility/Commands/PresetCommand.cs index 48c35ef1a443..8fa66d918b59 100644 --- a/util/SeederUtility/Commands/PresetCommand.cs +++ b/util/SeederUtility/Commands/PresetCommand.cs @@ -1,4 +1,5 @@ -using Bit.Seeder.Recipes; +using System.Text.Json; +using Bit.Seeder.Recipes; using Bit.Seeder.Services; using Bit.SeederUtility.Configuration; using Bit.SeederUtility.Helpers; @@ -18,7 +19,7 @@ public void Execute(PresetArgs args) if (args.List) { - PrintAvailablePresets(); + PrintAvailablePresets(args.GetOutputFormat()); return; } @@ -89,7 +90,7 @@ private static void RunIndividualPreset(PresetArgs args) ConsoleOutput.PrintMangleMap(deps); } - private static void PrintAvailablePresets() + private static void PrintAvailablePresets(OutputFormat format = OutputFormat.Text) { var available = PresetCatalogService.ListAvailable(); @@ -108,6 +109,17 @@ private static void PrintAvailablePresets() } } + if (format == OutputFormat.Json) + { + var output = new + { + organization = orgPresets, + individual = individualPresets, + }; + Console.WriteLine(JsonSerializer.Serialize(output, new JsonSerializerOptions { WriteIndented = true })); + return; + } + Console.WriteLine("Organization Presets:"); foreach (var preset in orgPresets) { diff --git a/util/SeederUtility/Program.cs b/util/SeederUtility/Program.cs index b9abfb5d7b13..2b0a245f8fd3 100644 --- a/util/SeederUtility/Program.cs +++ b/util/SeederUtility/Program.cs @@ -73,13 +73,13 @@ private static void PrintBanner() continue; } - Console.WriteLine($"{color}{line[minIndent..]}{reset}"); + Console.Error.WriteLine($"{color}{line[minIndent..]}{reset}"); } } - Console.WriteLine($" {bold}{cyan}╔══════════════════════════════════════════╗{reset}"); - Console.WriteLine($" {bold}{cyan}║ SEEDER UTILITY ║{reset}"); - Console.WriteLine($" {bold}{cyan}╚══════════════════════════════════════════╝{reset}"); + Console.Error.WriteLine($" {bold}{cyan}╔══════════════════════════════════════════╗{reset}"); + Console.Error.WriteLine($" {bold}{cyan}║ SEEDER UTILITY ║{reset}"); + Console.Error.WriteLine($" {bold}{cyan}╚══════════════════════════════════════════╝{reset}"); } [Subcommand]