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);
+ }
+ }
+}