From b5e1e9c8583e31537d83e31e016f3a2edcf66585 Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Mon, 18 Apr 2022 14:55:51 -0700 Subject: [PATCH] init kubectl (#830) * init kubectl * swagger version into assembly --- kubernetes-client.sln | 36 +++++++++++-- .../GeneratedApiVersion.cs | 7 +++ .../KubernetesClient.Basic.csproj | 2 +- .../Beta/AsyncKubectl.Version.cs | 23 +++++++++ .../Beta/AsyncKubectl.cs | 11 ++++ .../Beta/Kubectl.Version.cs | 12 +++++ src/KubernetesClient.Kubectl/Beta/Kubectl.cs | 11 ++++ .../KubernetesClient.Kubectl.csproj | 14 ++++++ .../GeneratedModelVersion.cs | 7 +++ .../KubernetesClient.Models.csproj | 2 +- .../KubernetesClientSourceGenerator.cs | 6 +++ .../VersionGenerator.cs | 12 +++++ .../{MnikubeTests.cs => MinikubeTests.cs} | 6 +-- tests/Kubectl.Tests/Kubectl.Tests.csproj | 39 +++++++++++++++ tests/Kubectl.Tests/KubectlTests.Version.cs | 32 ++++++++++++ tests/Kubectl.Tests/KubectlTests.cs | 50 +++++++++++++++++++ 16 files changed, 262 insertions(+), 8 deletions(-) create mode 100644 src/KubernetesClient.Basic/GeneratedApiVersion.cs create mode 100644 src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Version.cs create mode 100644 src/KubernetesClient.Kubectl/Beta/AsyncKubectl.cs create mode 100644 src/KubernetesClient.Kubectl/Beta/Kubectl.Version.cs create mode 100644 src/KubernetesClient.Kubectl/Beta/Kubectl.cs create mode 100644 src/KubernetesClient.Kubectl/KubernetesClient.Kubectl.csproj create mode 100644 src/KubernetesClient.Models/GeneratedModelVersion.cs create mode 100644 src/LibKubernetesGenerator/VersionGenerator.cs rename tests/E2E.Tests/{MnikubeTests.cs => MinikubeTests.cs} (99%) create mode 100644 tests/Kubectl.Tests/Kubectl.Tests.csproj create mode 100644 tests/Kubectl.Tests/KubectlTests.Version.cs create mode 100644 tests/Kubectl.Tests/KubectlTests.cs diff --git a/kubernetes-client.sln b/kubernetes-client.sln index 825fa11..a2cb9d3 100644 --- a/kubernetes-client.sln +++ b/kubernetes-client.sln @@ -55,11 +55,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubernetesClient.Basic", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubernetesClient.Classic", "src\KubernetesClient.Classic\KubernetesClient.Classic.csproj", "{80F19E8A-F097-4AA4-A68C-D417B96BBC68}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KubernetesClient.Classic.Tests", "tests\KubernetesClient.Classic.Tests\KubernetesClient.Classic.Tests.csproj", "{FD90C861-56C6-4536-B7F5-AC7779296384}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubernetesClient.Classic.Tests", "tests\KubernetesClient.Classic.Tests\KubernetesClient.Classic.Tests.csproj", "{FD90C861-56C6-4536-B7F5-AC7779296384}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csrApproval", "examples\csrApproval\csrApproval.csproj", "{F626860C-F141-45B3-9DDD-88AD3932ACAF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "csrApproval", "examples\csrApproval\csrApproval.csproj", "{F626860C-F141-45B3-9DDD-88AD3932ACAF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "restart", "examples\restart\restart.csproj", "{973CCB4A-F344-4C4F-81A5-0F40F7F43C07}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "restart", "examples\restart\restart.csproj", "{973CCB4A-F344-4C4F-81A5-0F40F7F43C07}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubernetesClient.Kubectl", "src\KubernetesClient.Kubectl\KubernetesClient.Kubectl.csproj", "{21201F30-5463-4FC6-93C3-FBF157F0D46C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kubectl.Tests", "tests\Kubectl.Tests\Kubectl.Tests.csproj", "{9128F6DC-6B7A-417F-937A-90461D6989A8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -383,6 +387,30 @@ Global {973CCB4A-F344-4C4F-81A5-0F40F7F43C07}.Release|x64.Build.0 = Release|Any CPU {973CCB4A-F344-4C4F-81A5-0F40F7F43C07}.Release|x86.ActiveCfg = Release|Any CPU {973CCB4A-F344-4C4F-81A5-0F40F7F43C07}.Release|x86.Build.0 = Release|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Debug|x64.ActiveCfg = Debug|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Debug|x64.Build.0 = Debug|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Debug|x86.ActiveCfg = Debug|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Debug|x86.Build.0 = Debug|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Release|Any CPU.Build.0 = Release|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Release|x64.ActiveCfg = Release|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Release|x64.Build.0 = Release|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Release|x86.ActiveCfg = Release|Any CPU + {21201F30-5463-4FC6-93C3-FBF157F0D46C}.Release|x86.Build.0 = Release|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Debug|x64.ActiveCfg = Debug|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Debug|x64.Build.0 = Debug|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Debug|x86.ActiveCfg = Debug|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Debug|x86.Build.0 = Debug|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Release|Any CPU.Build.0 = Release|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Release|x64.ActiveCfg = Release|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Release|x64.Build.0 = Release|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Release|x86.ActiveCfg = Release|Any CPU + {9128F6DC-6B7A-417F-937A-90461D6989A8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -414,6 +442,8 @@ Global {FD90C861-56C6-4536-B7F5-AC7779296384} = {8AF4A5C2-F0CE-47D5-A4C5-FE4AB83CA509} {F626860C-F141-45B3-9DDD-88AD3932ACAF} = {B70AFB57-57C9-46DC-84BE-11B7DDD34B40} {973CCB4A-F344-4C4F-81A5-0F40F7F43C07} = {B70AFB57-57C9-46DC-84BE-11B7DDD34B40} + {21201F30-5463-4FC6-93C3-FBF157F0D46C} = {3D1864AA-1FFC-4512-BB13-46055E410F73} + {9128F6DC-6B7A-417F-937A-90461D6989A8} = {8AF4A5C2-F0CE-47D5-A4C5-FE4AB83CA509} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {049A763A-C891-4E8D-80CF-89DD3E22ADC7} diff --git a/src/KubernetesClient.Basic/GeneratedApiVersion.cs b/src/KubernetesClient.Basic/GeneratedApiVersion.cs new file mode 100644 index 0000000..ab1d4d8 --- /dev/null +++ b/src/KubernetesClient.Basic/GeneratedApiVersion.cs @@ -0,0 +1,7 @@ +namespace k8s; + +public static class GeneratedApiVersion +{ + public const string AssemblyVersion = ThisAssembly.AssemblyInformationalVersion; + public const string SwaggerVersion = ThisAssembly.KubernetesSwaggerVersion; +} diff --git a/src/KubernetesClient.Basic/KubernetesClient.Basic.csproj b/src/KubernetesClient.Basic/KubernetesClient.Basic.csproj index 8481747..353630c 100644 --- a/src/KubernetesClient.Basic/KubernetesClient.Basic.csproj +++ b/src/KubernetesClient.Basic/KubernetesClient.Basic.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Version.cs b/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Version.cs new file mode 100644 index 0000000..c4b4286 --- /dev/null +++ b/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Version.cs @@ -0,0 +1,23 @@ +using k8s.Models; + +namespace k8s.kubectl.beta; + +public partial class AsyncKubectl +{ + private const string AsssemblyVersion = ThisAssembly.AssemblyInformationalVersion; + + public record KubernetesSDKVersion + { + public string ClientVersion { get; init; } = AsssemblyVersion; + + public string ClientSwaggerVersion { get; init; } = GeneratedApiVersion.SwaggerVersion; + + public VersionInfo ServerVersion { get; init; } = default!; + } + + public async Task Version(CancellationToken cancellationToken = default) + { + var serverVersion = await client.GetCodeAsync(cancellationToken).ConfigureAwait(false); + return new KubernetesSDKVersion { ServerVersion = serverVersion }; + } +} diff --git a/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.cs b/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.cs new file mode 100644 index 0000000..41f0166 --- /dev/null +++ b/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.cs @@ -0,0 +1,11 @@ +namespace k8s.kubectl.beta; + +public partial class AsyncKubectl +{ + private readonly IKubernetes client; + + public AsyncKubectl(IKubernetes client) + { + this.client = client; + } +} diff --git a/src/KubernetesClient.Kubectl/Beta/Kubectl.Version.cs b/src/KubernetesClient.Kubectl/Beta/Kubectl.Version.cs new file mode 100644 index 0000000..ffcb493 --- /dev/null +++ b/src/KubernetesClient.Kubectl/Beta/Kubectl.Version.cs @@ -0,0 +1,12 @@ +using static k8s.kubectl.beta.AsyncKubectl; + +namespace k8s.kubectl.beta; + +public partial class Kubectl +{ + // TODO should auto generate this + public KubernetesSDKVersion Version() + { + return client.Version().GetAwaiter().GetResult(); + } +} diff --git a/src/KubernetesClient.Kubectl/Beta/Kubectl.cs b/src/KubernetesClient.Kubectl/Beta/Kubectl.cs new file mode 100644 index 0000000..699bbeb --- /dev/null +++ b/src/KubernetesClient.Kubectl/Beta/Kubectl.cs @@ -0,0 +1,11 @@ +namespace k8s.kubectl.beta; + +public partial class Kubectl +{ + private readonly AsyncKubectl client; + + public Kubectl(IKubernetes client) + { + this.client = new AsyncKubectl(client); + } +} diff --git a/src/KubernetesClient.Kubectl/KubernetesClient.Kubectl.csproj b/src/KubernetesClient.Kubectl/KubernetesClient.Kubectl.csproj new file mode 100644 index 0000000..794a3d8 --- /dev/null +++ b/src/KubernetesClient.Kubectl/KubernetesClient.Kubectl.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + enable + enable + k8s.kubectl + + + + + + + diff --git a/src/KubernetesClient.Models/GeneratedModelVersion.cs b/src/KubernetesClient.Models/GeneratedModelVersion.cs new file mode 100644 index 0000000..e1b5ccb --- /dev/null +++ b/src/KubernetesClient.Models/GeneratedModelVersion.cs @@ -0,0 +1,7 @@ +namespace k8s.Models; + +public static class GeneratedModelVersion +{ + public const string AssemblyVersion = ThisAssembly.AssemblyInformationalVersion; + public const string SwaggerVersion = ThisAssembly.KubernetesSwaggerVersion; +} diff --git a/src/KubernetesClient.Models/KubernetesClient.Models.csproj b/src/KubernetesClient.Models/KubernetesClient.Models.csproj index f6b197b..60ba5c4 100644 --- a/src/KubernetesClient.Models/KubernetesClient.Models.csproj +++ b/src/KubernetesClient.Models/KubernetesClient.Models.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs b/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs index 087f2ba..325e83c 100644 --- a/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs +++ b/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs @@ -67,6 +67,7 @@ namespace LibKubernetesGenerator builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); + builder.RegisterType(); var container = builder.Build(); // TODO move to Handlebars.Net @@ -100,6 +101,11 @@ namespace LibKubernetesGenerator { container.Resolve().Generate(swagger, context); } + + if (generators.Contains("version")) + { + container.Resolve().Generate(swagger, context); + } } } diff --git a/src/LibKubernetesGenerator/VersionGenerator.cs b/src/LibKubernetesGenerator/VersionGenerator.cs new file mode 100644 index 0000000..c1a1969 --- /dev/null +++ b/src/LibKubernetesGenerator/VersionGenerator.cs @@ -0,0 +1,12 @@ +using Microsoft.CodeAnalysis; +using NSwag; + +namespace LibKubernetesGenerator; + +internal class VersionGenerator +{ + public void Generate(OpenApiDocument swagger, GeneratorExecutionContext context) + { + context.AddSource("k8sver.cs", $"// \n" + "internal static partial class ThisAssembly { internal const string KubernetesSwaggerVersion = \"" + swagger.Info.Version + "\";}"); + } +} diff --git a/tests/E2E.Tests/MnikubeTests.cs b/tests/E2E.Tests/MinikubeTests.cs similarity index 99% rename from tests/E2E.Tests/MnikubeTests.cs rename to tests/E2E.Tests/MinikubeTests.cs index a05e134..da08e9a 100644 --- a/tests/E2E.Tests/MnikubeTests.cs +++ b/tests/E2E.Tests/MinikubeTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -17,7 +17,7 @@ using Xunit; namespace k8s.E2E { - public class MnikubeTests + public class MinikubeTests { [MinikubeFact] public void SimpleTest() @@ -548,7 +548,7 @@ namespace k8s.E2E } - private static IKubernetes CreateClient() + public static IKubernetes CreateClient() { return new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()); } diff --git a/tests/Kubectl.Tests/Kubectl.Tests.csproj b/tests/Kubectl.Tests/Kubectl.Tests.csproj new file mode 100644 index 0000000..ac0dbdf --- /dev/null +++ b/tests/Kubectl.Tests/Kubectl.Tests.csproj @@ -0,0 +1,39 @@ + + + + net6.0 + enable + enable + false + k8s.kubectl.Tests + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + PreserveNewest + + + \ No newline at end of file diff --git a/tests/Kubectl.Tests/KubectlTests.Version.cs b/tests/Kubectl.Tests/KubectlTests.Version.cs new file mode 100644 index 0000000..04c7609 --- /dev/null +++ b/tests/Kubectl.Tests/KubectlTests.Version.cs @@ -0,0 +1,32 @@ +using k8s.E2E; +using System.Text.Json; +using Xunit; + +namespace k8s.kubectl.Tests; + +public partial class KubectlTests +{ + [MinikubeFact] + public void Version() + { + var client = CreateClient(); + var version = client.Version(); + var serverobj = version.ServerVersion; + + var output = RunKubectl("version"); + + var serverstr = output.Split('\n').Skip(1).First().Trim(); + + Assert.Equal(serverstr, $"Server Version: version.Info{{Major:\"{serverobj.Major}\", Minor:\"{serverobj.Minor}\", GitVersion:\"{serverobj.GitVersion}\", GitCommit:\"{serverobj.GitCommit}\", GitTreeState:\"{serverobj.GitTreeState}\", BuildDate:\"{serverobj.BuildDate}\", GoVersion:\"{serverobj.GoVersion}\", Compiler:\"{serverobj.Compiler}\", Platform:\"{serverobj.Platform}\"}}"); + + dynamic? swagger = JsonSerializer.Deserialize(File.OpenRead("swagger.json"), new + { + info = new + { + version = "", + }, + }.GetType()); + + Assert.Equal(swagger?.info.version, version.ClientSwaggerVersion); + } +} diff --git a/tests/Kubectl.Tests/KubectlTests.cs b/tests/Kubectl.Tests/KubectlTests.cs new file mode 100644 index 0000000..b16b304 --- /dev/null +++ b/tests/Kubectl.Tests/KubectlTests.cs @@ -0,0 +1,50 @@ +using k8s.E2E; +using k8s.kubectl.beta; +using System.Diagnostics; + +namespace k8s.kubectl.Tests; + +public partial class KubectlTests +{ + private Kubectl CreateClient() + { + return new Kubectl(MinikubeTests.CreateClient()); + } + + private string RunKubectl(string args) + { + var p = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "kubectl", + Arguments = args, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + }, + }; + + p.Start(); + + try + { + if (!p.WaitForExit((int)TimeSpan.FromSeconds(30).TotalMilliseconds)) + { + throw new Exception("kubectl timed out"); + } + + if (p.ExitCode != 0) + { + throw new Exception(p.StandardError.ReadToEnd()); + } + + return p.StandardOutput.ReadToEnd(); + } + finally + { + p.Kill(true); + } + } +}