From 44811997e46c69108ea5de90eea7f09722cb91bc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 02:50:23 +0000 Subject: [PATCH] fix(deps): update dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christoph Bühler --- src/Directory.Build.props | 2 +- .../KubeOps.Abstractions.csproj | 2 +- src/KubeOps.Cli/Arguments.cs | 30 ++++--- .../Commands/Generator/Generate.cs | 5 +- .../Commands/Generator/OperatorGenerator.cs | 28 +++--- .../Commands/Management/Install.cs | 24 +++--- .../Commands/Management/Uninstall.cs | 24 +++--- src/KubeOps.Cli/Commands/Utilities/Version.cs | 4 +- src/KubeOps.Cli/KubeOps.Cli.csproj | 2 +- src/KubeOps.Cli/Options.cs | 86 ++++++++++--------- src/KubeOps.Cli/Program.cs | 34 +++----- .../Properties/launchSettings.json | 5 ++ src/KubeOps.Operator/KubeOps.Operator.csproj | 2 +- .../KubeOps.Transpiler.csproj | 2 +- .../Management/Install.Integration.Test.cs | 17 ++-- 15 files changed, 138 insertions(+), 129 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 80413abf..028b3f45 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -43,7 +43,7 @@ PrivateAssets="all" Condition="$(MSBuildProjectExtension) == '.csproj'" /> - + diff --git a/src/KubeOps.Cli/Arguments.cs b/src/KubeOps.Cli/Arguments.cs index abf10c57..cc70db2b 100644 --- a/src/KubeOps.Cli/Arguments.cs +++ b/src/KubeOps.Cli/Arguments.cs @@ -8,9 +8,9 @@ namespace KubeOps.Cli; internal static class Arguments { - public static readonly Argument SolutionOrProjectFile = new( - "sln/csproj file", - () => + public static readonly Argument SolutionOrProjectFile = new("sln/csproj file") + { + DefaultValueFactory = result => { var projectFile = Directory.EnumerateFiles( @@ -24,20 +24,26 @@ var slnFile "*.sln") .Select(f => new FileInfo(f)) .FirstOrDefault(); - - return (projectFile, slnFile) switch + var file = (projectFile, slnFile) switch { ({ } prj, _) => prj, (_, { } sln) => sln, _ => null, }; + + if (file is not null) + { + return file; + } + + result.AddError("No solution or project file found in the current directory, and none was provided."); + return new FileInfo("not-found"); }, - "A solution or project file where entities are located. " + - "If omitted, the current directory is searched for a *.csproj or *.sln file. " + - "If an *.sln file is used, all projects in the solution (with the newest framework) will be searched for entities. " + - "This behaviour can be filtered by using the --project and --target-framework option."); + Description = "A solution or project file where entities are located. " + + "If omitted, the current directory is searched for a *.csproj or *.sln file. " + + "If an *.sln file is used, all projects in the solution (with the newest framework) will be searched for entities. " + + "This behaviour can be filtered by using the --project and --target-framework option.", + }; - public static readonly Argument OperatorName = new( - "name", - "Name of the operator."); + public static readonly Argument OperatorName = new("name") { Description = "Name of the operator.", }; } diff --git a/src/KubeOps.Cli/Commands/Generator/Generate.cs b/src/KubeOps.Cli/Commands/Generator/Generate.cs index 1a5445f2..743db12b 100644 --- a/src/KubeOps.Cli/Commands/Generator/Generate.cs +++ b/src/KubeOps.Cli/Commands/Generator/Generate.cs @@ -17,9 +17,8 @@ public static Command Command { OperatorGenerator.Command, }; - cmd.AddAlias("gen"); - cmd.AddAlias("g"); - cmd.SetHandler(ctx => ctx.HelpBuilder.Write(cmd, Console.Out)); + cmd.Aliases.Add("gen"); + cmd.Aliases.Add("g"); return cmd; } diff --git a/src/KubeOps.Cli/Commands/Generator/OperatorGenerator.cs b/src/KubeOps.Cli/Commands/Generator/OperatorGenerator.cs index 8664cc67..227eb389 100644 --- a/src/KubeOps.Cli/Commands/Generator/OperatorGenerator.cs +++ b/src/KubeOps.Cli/Commands/Generator/OperatorGenerator.cs @@ -39,21 +39,21 @@ public static Command Command Arguments.OperatorName, Arguments.SolutionOrProjectFile, }; - cmd.AddAlias("op"); - cmd.SetHandler(ctx => Handler(AnsiConsole.Console, ctx)); + cmd.Aliases.Add("op"); + cmd.SetAction(result => Handler(AnsiConsole.Console, result)); return cmd; } } - internal static async Task Handler(IAnsiConsole console, InvocationContext ctx) + internal static async Task Handler(IAnsiConsole console, ParseResult parseResult) { - var name = ctx.ParseResult.GetValueForArgument(Arguments.OperatorName); - var file = ctx.ParseResult.GetValueForArgument(Arguments.SolutionOrProjectFile); - var outPath = ctx.ParseResult.GetValueForOption(Options.OutputPath); - var format = ctx.ParseResult.GetValueForOption(Options.OutputFormat); - var dockerImage = ctx.ParseResult.GetValueForOption(Options.AccessibleDockerImage)!; - var dockerImageTag = ctx.ParseResult.GetValueForOption(Options.AccessibleDockerTag)!; + var name = parseResult.GetValue(Arguments.OperatorName) ?? "operator"; + var file = parseResult.GetValue(Arguments.SolutionOrProjectFile); + var outPath = parseResult.GetValue(Options.OutputPath); + var format = parseResult.GetValue(Options.OutputFormat); + var dockerImage = parseResult.GetValue(Options.AccessibleDockerImage)!; + var dockerImageTag = parseResult.GetValue(Options.AccessibleDockerTag)!; var result = new ResultOutput(console, format); console.WriteLine("Generate operator resources."); @@ -65,8 +65,8 @@ internal static async Task Handler(IAnsiConsole console, InvocationContext ctx) { Extension: ".sln", Exists: true } => await AssemblyLoader.ForSolution( console, file, - ctx.ParseResult.GetValueForOption(Options.SolutionProjectRegex), - ctx.ParseResult.GetValueForOption(Options.TargetFramework)), + parseResult.GetValue(Options.SolutionProjectRegex), + parseResult.GetValue(Options.TargetFramework)), { Exists: false } => throw new FileNotFoundException($"The file {file.Name} does not exist."), _ => throw new NotSupportedException("Only *.csproj and *.sln files are supported."), }; @@ -111,7 +111,7 @@ internal static async Task Handler(IAnsiConsole console, InvocationContext ctx) new DeploymentGenerator(format).Generate(result); console.MarkupLine("[green]Generate CRDs.[/]"); - new CrdGenerator(parser, Array.Empty(), format).Generate(result); + new CrdGenerator(parser, [], format).Generate(result); } result.Add( @@ -158,7 +158,7 @@ internal static async Task Handler(IAnsiConsole console, InvocationContext ctx) if (outPath is not null) { - if (ctx.ParseResult.GetValueForOption(Options.ClearOutputPath)) + if (parseResult.GetValue(Options.ClearOutputPath)) { console.MarkupLine("[yellow]Clear output path.[/]"); try @@ -182,5 +182,7 @@ internal static async Task Handler(IAnsiConsole console, InvocationContext ctx) { result.Write(); } + + return ExitCodes.Success; } } diff --git a/src/KubeOps.Cli/Commands/Management/Install.cs b/src/KubeOps.Cli/Commands/Management/Install.cs index 41738596..a6491c94 100644 --- a/src/KubeOps.Cli/Commands/Management/Install.cs +++ b/src/KubeOps.Cli/Commands/Management/Install.cs @@ -30,20 +30,20 @@ public static Command Command Options.TargetFramework, Arguments.SolutionOrProjectFile, }; - cmd.AddAlias("i"); - cmd.SetHandler(ctx => Handler( + cmd.Aliases.Add("i"); + cmd.SetAction(result => Handler( AnsiConsole.Console, new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()), - ctx)); + result)); return cmd; } } - internal static async Task Handler(IAnsiConsole console, IKubernetes client, InvocationContext ctx) + internal static async Task Handler(IAnsiConsole console, IKubernetes client, ParseResult parseResult) { - var file = ctx.ParseResult.GetValueForArgument(Arguments.SolutionOrProjectFile); - var force = ctx.ParseResult.GetValueForOption(Options.Force); + var file = parseResult.GetValue(Arguments.SolutionOrProjectFile); + var force = parseResult.GetValue(Options.Force); var parser = file switch { @@ -51,8 +51,8 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv { Extension: ".sln", Exists: true } => await AssemblyLoader.ForSolution( console, file, - ctx.ParseResult.GetValueForOption(Options.SolutionProjectRegex), - ctx.ParseResult.GetValueForOption(Options.TargetFramework)), + parseResult.GetValue(Options.SolutionProjectRegex), + parseResult.GetValue(Options.TargetFramework)), { Exists: false } => throw new FileNotFoundException($"The file {file.Name} does not exist."), _ => throw new NotSupportedException("Only *.csproj and *.sln files are supported."), }; @@ -62,8 +62,7 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv if (crds.Count == 0) { console.WriteLine("No CRDs found. Exiting."); - ctx.ExitCode = ExitCodes.Success; - return; + return ExitCodes.Success; } console.WriteLine($"Found {crds.Count} CRDs."); @@ -84,8 +83,7 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv $"""[yellow]CRD "{crd.Spec.Group}/{crd.Spec.Names.Kind}" already exists.[/]"""); if (!force && !await console.ConfirmAsync("[yellow]Should the CRD be overwritten?[/]")) { - ctx.ExitCode = ExitCodes.Aborted; - return; + return ExitCodes.Aborted; } crd.Metadata.ResourceVersion = existing.ResourceVersion(); @@ -112,5 +110,7 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv throw; } } + + return ExitCodes.Success; } } diff --git a/src/KubeOps.Cli/Commands/Management/Uninstall.cs b/src/KubeOps.Cli/Commands/Management/Uninstall.cs index 3b8dd516..d32e064e 100644 --- a/src/KubeOps.Cli/Commands/Management/Uninstall.cs +++ b/src/KubeOps.Cli/Commands/Management/Uninstall.cs @@ -30,20 +30,20 @@ public static Command Command Options.TargetFramework, Arguments.SolutionOrProjectFile, }; - cmd.AddAlias("u"); - cmd.SetHandler(ctx => Handler( + cmd.Aliases.Add("u"); + cmd.SetAction(result => Handler( AnsiConsole.Console, new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()), - ctx)); + result)); return cmd; } } - internal static async Task Handler(IAnsiConsole console, IKubernetes client, InvocationContext ctx) + internal static async Task Handler(IAnsiConsole console, IKubernetes client, ParseResult parseResult) { - var file = ctx.ParseResult.GetValueForArgument(Arguments.SolutionOrProjectFile); - var force = ctx.ParseResult.GetValueForOption(Options.Force); + var file = parseResult.GetValue(Arguments.SolutionOrProjectFile); + var force = parseResult.GetValue(Options.Force); var parser = file switch { @@ -51,8 +51,8 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv { Extension: ".sln", Exists: true } => await AssemblyLoader.ForSolution( console, file, - ctx.ParseResult.GetValueForOption(Options.SolutionProjectRegex), - ctx.ParseResult.GetValueForOption(Options.TargetFramework)), + parseResult.GetValue(Options.SolutionProjectRegex), + parseResult.GetValue(Options.TargetFramework)), { Exists: false } => throw new FileNotFoundException($"The file {file.Name} does not exist."), _ => throw new NotSupportedException("Only *.csproj and *.sln files are supported."), }; @@ -62,15 +62,13 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv if (crds.Count == 0) { console.WriteLine("No CRDs found. Exiting."); - ctx.ExitCode = ExitCodes.Success; - return; + return ExitCodes.Success; } console.WriteLine($"Found {crds.Count} CRDs."); if (!force && !await console.ConfirmAsync("[red]Should the CRDs be uninstalled?[/]", false)) { - ctx.ExitCode = ExitCodes.Aborted; - return; + return ExitCodes.Aborted; } console.WriteLine($"""Starting uninstall from cluster with url "{client.BaseUri}"."""); @@ -109,5 +107,7 @@ internal static async Task Handler(IAnsiConsole console, IKubernetes client, Inv throw; } } + + return ExitCodes.Success; } } diff --git a/src/KubeOps.Cli/Commands/Utilities/Version.cs b/src/KubeOps.Cli/Commands/Utilities/Version.cs index 63b98678..3ad714c8 100644 --- a/src/KubeOps.Cli/Commands/Utilities/Version.cs +++ b/src/KubeOps.Cli/Commands/Utilities/Version.cs @@ -19,8 +19,8 @@ public static Command Command var cmd = new Command( "api-version", "Prints the actual server version of the connected kubernetes cluster."); - cmd.AddAlias("av"); - cmd.SetHandler(() => + cmd.Aliases.Add("av"); + cmd.SetAction(_ => Handler(AnsiConsole.Console, new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()))); return cmd; diff --git a/src/KubeOps.Cli/KubeOps.Cli.csproj b/src/KubeOps.Cli/KubeOps.Cli.csproj index b45ee097..5a2b8176 100644 --- a/src/KubeOps.Cli/KubeOps.Cli.csproj +++ b/src/KubeOps.Cli/KubeOps.Cli.csproj @@ -29,7 +29,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/KubeOps.Cli/Options.cs b/src/KubeOps.Cli/Options.cs index 29c3ae44..a1270dab 100644 --- a/src/KubeOps.Cli/Options.cs +++ b/src/KubeOps.Cli/Options.cs @@ -11,47 +11,55 @@ namespace KubeOps.Cli; internal static class Options { - public static readonly Option OutputFormat = new( - "--format", - () => Output.OutputFormat.Yaml, - "The format of the generated output."); - - public static readonly Option OutputPath = new( - "--out", - "The path the command will write the files to. If omitted, prints output to console."); - - public static readonly Option TargetFramework = new( - ["--target-framework", "--tfm"], - description: "Target framework of projects in the solution to search for entities. " + - "If omitted, the newest framework is used."); - - public static readonly Option SolutionProjectRegex = new( - "--project", - parseArgument: result => + public static readonly Option OutputFormat = new("--format") + { + Description = "The format of the generated output.", + DefaultValueFactory = _ => Output.OutputFormat.Yaml, + }; + + public static readonly Option OutputPath = new("--out") + { + Description = "The path the command will write the files to. If omitted, prints output to console.", + }; + + public static readonly Option TargetFramework = new("--target-framework", "--tfm") + { + Description = "Target framework of projects in the solution to search for entities. " + + "If omitted, the newest framework is used.", + }; + + public static readonly Option SolutionProjectRegex = new("--project") + { + Description = "Regex pattern to filter projects in the solution to search for entities. " + + "If omitted, all projects are searched.", + CustomParser = result => { var value = result.Tokens.Single().Value; return new Regex(value); }, - description: "Regex pattern to filter projects in the solution to search for entities. " + - "If omitted, all projects are searched."); - - public static readonly Option Force = new( - ["--force", "-f"], - () => false, - description: "Do not bother the user with questions and just do it."); - - public static readonly Option ClearOutputPath = new( - ["--clear-out"], - () => false, - description: "Clear the output path before generating resources."); - - public static readonly Option AccessibleDockerImage = new( - "--docker-image", - () => "accessible-docker-image", - description: "An accessible docker image to deploy"); - - public static readonly Option AccessibleDockerTag = new( - "--docker-image-tag", - () => "latest", - description: "Tag for an accessible docker image to deploy"); + }; + + public static readonly Option Force = new("--force", "-f") + { + Description = "Do not bother the user with questions and just do it.", + DefaultValueFactory = _ => false, + }; + + public static readonly Option ClearOutputPath = new("--clear-out") + { + Description = "Clear the output path before generating resources.", + DefaultValueFactory = _ => false, + }; + + public static readonly Option AccessibleDockerImage = new("--docker-image") + { + Description = "An accessible docker image to deploy.", + DefaultValueFactory = _ => "accessible-docker-image", + }; + + public static readonly Option AccessibleDockerTag = new("--docker-image-tag") + { + Description = "Tag for an accessible docker image to deploy.", + DefaultValueFactory = _ => "latest", + }; } diff --git a/src/KubeOps.Cli/Program.cs b/src/KubeOps.Cli/Program.cs index 766bb623..d4f1dfa5 100644 --- a/src/KubeOps.Cli/Program.cs +++ b/src/KubeOps.Cli/Program.cs @@ -3,30 +3,22 @@ // See the LICENSE file in the project root for more information. using System.CommandLine; -using System.CommandLine.Builder; -using System.CommandLine.Parsing; +using System.CommandLine.Invocation; -using KubeOps.Cli; using KubeOps.Cli.Commands.Generator; using KubeOps.Cli.Commands.Management; -using Spectre.Console; - using Version = KubeOps.Cli.Commands.Utilities.Version; -return await new CommandLineBuilder(new RootCommand( - "CLI for KubeOps. Commandline tool to help with management tasks such as generating or installing CRDs.") - { - Generate.Command, Version.Command, Install.Command, Uninstall.Command, - }) - .UseDefaults() - .UseParseErrorReporting(ExitCodes.UsageError) - .UseExceptionHandler((ex, ctx) => - { - AnsiConsole.MarkupLineInterpolated( - $"[red]An error occurred whiled executing {ctx.ParseResult.CommandResult.Command}[/]"); - AnsiConsole.MarkupLineInterpolated($"[red]{ex.Message}[/]"); - ctx.ExitCode = ExitCodes.Error; - }) - .Build() - .InvokeAsync(args); +var parseResult = new RootCommand( + "CLI for KubeOps. Commandline tool to help with management tasks such as generating or installing CRDs.") +{ + Generate.Command, Version.Command, Install.Command, Uninstall.Command, +}.Parse(args); +if (parseResult.Action is ParseErrorAction errorAction) +{ + errorAction.ShowHelp = true; + errorAction.ShowTypoCorrections = true; +} + +await parseResult.InvokeAsync(); diff --git a/src/KubeOps.Cli/Properties/launchSettings.json b/src/KubeOps.Cli/Properties/launchSettings.json index 7d962138..dd066871 100644 --- a/src/KubeOps.Cli/Properties/launchSettings.json +++ b/src/KubeOps.Cli/Properties/launchSettings.json @@ -25,6 +25,11 @@ "commandName": "Project", "workingDirectory": "$(ProjectDir)", "commandLineArgs": "u ../../examples/Operator/Operator.csproj -f" + }, + "CLI Version": { + "commandName": "Project", + "workingDirectory": "$(ProjectDir)", + "commandLineArgs": "av" } } } diff --git a/src/KubeOps.Operator/KubeOps.Operator.csproj b/src/KubeOps.Operator/KubeOps.Operator.csproj index 5361c6e6..27eea800 100644 --- a/src/KubeOps.Operator/KubeOps.Operator.csproj +++ b/src/KubeOps.Operator/KubeOps.Operator.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj b/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj index 3fb815a2..d9343d68 100644 --- a/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj +++ b/src/KubeOps.Transpiler/KubeOps.Transpiler.csproj @@ -15,7 +15,7 @@ - + diff --git a/test/KubeOps.Cli.Test/Management/Install.Integration.Test.cs b/test/KubeOps.Cli.Test/Management/Install.Integration.Test.cs index f3b26a24..62512a1b 100644 --- a/test/KubeOps.Cli.Test/Management/Install.Integration.Test.cs +++ b/test/KubeOps.Cli.Test/Management/Install.Integration.Test.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. -using System.CommandLine; -using System.CommandLine.Invocation; using System.Text; using FluentAssertions; @@ -24,31 +22,30 @@ public class InstallIntegrationTest "Operator.csproj"); [Fact - (Skip = "For some reason, the MetadataReferences are not loaded when the assembly parser is used from a test project.") + (Skip = + "For some reason, the MetadataReferences are not loaded when the assembly parser is used from a test project.") ] public async Task Should_Install_Crds_In_Cluster() { var console = new TestConsole(); var client = new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()); var cmd = Install.Command; - var ctx = new InvocationContext( - cmd.Parse(ProjectPath, "-f")); + var result = cmd.Parse([ProjectPath, "-f"]); - await Install.Handler(console, client, ctx); + await Install.Handler(console, client, result); } [Fact - (Skip = "We need to think of a good way to validate the kustomization given there is not real schema published") + (Skip = "We need to think of a good way to validate the kustomization given there is not real schema published") ] public async Task Should_Generate_Valid_Installers_In_Cluster() { var console = new TestConsole(); var client = new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()); var cmd = OperatorGenerator.Command; - var ctx = new InvocationContext( - cmd.Parse("operator", "test", ProjectPath)); + var result = cmd.Parse(["operator", "test", ProjectPath]); - await OperatorGenerator.Handler(console, ctx); + await OperatorGenerator.Handler(console, result); console.Output.Should().NotBeNull(); var separator = console.Lines.GroupBy(x => x).OrderByDescending(x => x.Count()).First().Key; var groups = new List();