diff --git a/.github/workflows/buildtest.yaml b/.github/workflows/buildtest.yaml index 1870d99e8..b97747c7b 100644 --- a/.github/workflows/buildtest.yaml +++ b/.github/workflows/buildtest.yaml @@ -17,12 +17,8 @@ jobs: dotnet-version: | 8.0.x 9.0.x - # - name: Check Format - # # don't check formatting on Windows b/c of CRLF issues. - # if: matrix.os == 'ubuntu-latest' - # run: dotnet format --severity error --verify-no-changes --exclude ./src/KubernetesClient/generated/ - name: Build - run: dotnet build --configuration Release -v detailed + run: dotnet build --configuration Release - name: Test run: dotnet test --configuration Release --collect:"Code Coverage;Format=Cobertura" --logger trx --results-directory TestResults --settings CodeCoverage.runsettings --no-build - name: Upload coverage to Codecov diff --git a/examples/csrApproval/Program.cs b/examples/csrApproval/Program.cs index fc94ae9a8..6c374105b 100644 --- a/examples/csrApproval/Program.cs +++ b/examples/csrApproval/Program.cs @@ -67,7 +67,15 @@ string GenerateCertificate(string name) var replace = new List { - new ("True", "Approved", DateTime.UtcNow, DateTime.UtcNow, "This certificate was approved by k8s client", "Approve"), + new V1CertificateSigningRequestCondition + { + Type = "Approved", + Status = "True", + Reason = "Approve", + Message = "This certificate was approved by k8s client", + LastUpdateTime = DateTime.UtcNow, + LastTransitionTime = DateTime.UtcNow, + }, }; readCert.Status.Conditions = replace; diff --git a/examples/customResource/cResource.cs b/examples/customResource/cResource.cs index f9df60b22..67440aee9 100644 --- a/examples/customResource/cResource.cs +++ b/examples/customResource/cResource.cs @@ -19,13 +19,13 @@ public override string ToString() } } - public class CResourceSpec + public record CResourceSpec { [JsonPropertyName("cityName")] public string CityName { get; set; } } - public class CResourceStatus : V1Status + public record CResourceStatus : V1Status { [JsonPropertyName("temperature")] public string Temperature { get; set; } diff --git a/examples/resize/Program.cs b/examples/resize/Program.cs index 58682c5b7..85fbeb9b2 100644 --- a/examples/resize/Program.cs +++ b/examples/resize/Program.cs @@ -23,7 +23,7 @@ { Requests = new Dictionary() { - ["cpu"] = new ResourceQuantity("100m"), + ["cpu"] = "100m", }, }, }, diff --git a/src/KubernetesClient.Aot/KubernetesClient.Aot.csproj b/src/KubernetesClient.Aot/KubernetesClient.Aot.csproj index 3ede68c48..55305a1a1 100644 --- a/src/KubernetesClient.Aot/KubernetesClient.Aot.csproj +++ b/src/KubernetesClient.Aot/KubernetesClient.Aot.csproj @@ -25,15 +25,13 @@ - + - - diff --git a/src/KubernetesClient.Classic/IsExternalInit.cs b/src/KubernetesClient.Classic/IsExternalInit.cs new file mode 100644 index 000000000..749f30858 --- /dev/null +++ b/src/KubernetesClient.Classic/IsExternalInit.cs @@ -0,0 +1,5 @@ +// IntOrString.cs(7,36): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported +namespace System.Runtime.CompilerServices +{ + internal static class IsExternalInit { } +} \ No newline at end of file diff --git a/src/KubernetesClient.Classic/KubernetesClient.Classic.csproj b/src/KubernetesClient.Classic/KubernetesClient.Classic.csproj index 1fad632d2..81070f066 100644 --- a/src/KubernetesClient.Classic/KubernetesClient.Classic.csproj +++ b/src/KubernetesClient.Classic/KubernetesClient.Classic.csproj @@ -27,17 +27,15 @@ - + - - diff --git a/src/KubernetesClient/IValidate.cs b/src/KubernetesClient/IValidate.cs deleted file mode 100644 index c81f553f2..000000000 --- a/src/KubernetesClient/IValidate.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace k8s -{ - /// - /// Object that allows self validation - /// - public interface IValidate - { - /// - /// Validate the object. - /// - void Validate(); - } -} diff --git a/src/KubernetesClient/Models/IntOrString.cs b/src/KubernetesClient/Models/IntOrString.cs new file mode 100644 index 000000000..e79ef2465 --- /dev/null +++ b/src/KubernetesClient/Models/IntOrString.cs @@ -0,0 +1,38 @@ +namespace k8s.Models +{ + [JsonConverter(typeof(IntOrStringJsonConverter))] + public struct IntOrString + { + public string? Value { get; private init; } + + public static implicit operator IntOrString(int v) + { + return Convert.ToString(v); + } + + public static implicit operator IntOrString(long v) + { + return Convert.ToString(v); + } + + public static implicit operator string(IntOrString v) + { + return v.Value; + } + + public static implicit operator IntOrString(string v) + { + return new IntOrString { Value = v }; + } + + public override string ToString() + { + return Value; + } + + public int ToInt() + { + return int.Parse(Value); + } + } +} diff --git a/src/KubernetesClient/Models/IntOrStringJsonConverter.cs b/src/KubernetesClient/Models/IntOrStringJsonConverter.cs index 9b665a30c..c7cbe273a 100644 --- a/src/KubernetesClient/Models/IntOrStringJsonConverter.cs +++ b/src/KubernetesClient/Models/IntOrStringJsonConverter.cs @@ -1,8 +1,8 @@ namespace k8s.Models { - internal sealed class IntOrStringJsonConverter : JsonConverter + internal sealed class IntOrStringJsonConverter : JsonConverter { - public override IntstrIntOrString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override IntOrString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { switch (reader.TokenType) { @@ -17,14 +17,14 @@ public override IntstrIntOrString Read(ref Utf8JsonReader reader, Type typeToCon throw new NotSupportedException(); } - public override void Write(Utf8JsonWriter writer, IntstrIntOrString value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, IntOrString value, JsonSerializerOptions options) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } - var s = value?.Value; + var s = value.Value; if (long.TryParse(s, out var intv)) { diff --git a/src/KubernetesClient/Models/IntOrStringYamlConverter.cs b/src/KubernetesClient/Models/IntOrStringYamlConverter.cs index 49116bd6c..514f2be91 100644 --- a/src/KubernetesClient/Models/IntOrStringYamlConverter.cs +++ b/src/KubernetesClient/Models/IntOrStringYamlConverter.cs @@ -7,7 +7,7 @@ public class IntOrStringYamlConverter : IYamlTypeConverter { public bool Accepts(Type type) { - return type == typeof(IntstrIntOrString); + return type == typeof(IntOrString); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) @@ -21,7 +21,7 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria return null; } - return new IntstrIntOrString(scalar?.Value); + return scalar?.Value; } finally { @@ -34,8 +34,8 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer) { - var obj = (IntstrIntOrString)value; - emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj?.Value)); + var obj = (IntOrString)value; + emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj.Value)); } } } diff --git a/src/KubernetesClient/Models/IntstrIntOrString.cs b/src/KubernetesClient/Models/IntstrIntOrString.cs deleted file mode 100644 index 6f378df9b..000000000 --- a/src/KubernetesClient/Models/IntstrIntOrString.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace k8s.Models -{ - [JsonConverter(typeof(IntOrStringJsonConverter))] - public partial class IntstrIntOrString - { - public static implicit operator IntstrIntOrString(int v) - { - return new IntstrIntOrString(Convert.ToString(v)); - } - - public static implicit operator IntstrIntOrString(long v) - { - return new IntstrIntOrString(Convert.ToString(v)); - } - - public static implicit operator string(IntstrIntOrString v) - { - return v?.Value; - } - - public static implicit operator IntstrIntOrString(string v) - { - return new IntstrIntOrString(v); - } - - protected bool Equals(IntstrIntOrString other) - { - return string.Equals(Value, other?.Value); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj.GetType() != GetType()) - { - return false; - } - - return Equals((IntstrIntOrString)obj); - } - - public override int GetHashCode() - { - return Value != null ? Value.GetHashCode() : 0; - } - } -} diff --git a/src/KubernetesClient/Models/KubernetesList.cs b/src/KubernetesClient/Models/KubernetesList.cs index 5a1e326de..069c410b2 100644 --- a/src/KubernetesClient/Models/KubernetesList.cs +++ b/src/KubernetesClient/Models/KubernetesList.cs @@ -40,24 +40,5 @@ public KubernetesList(IList items, string apiVersion = default, string kind = /// [JsonPropertyName("metadata")] public V1ListMeta Metadata { get; set; } - - /// - /// Validate the object. - /// - public void Validate() - { - if (Items == null) - { - throw new ArgumentNullException("Items"); - } - - if (Items != null) - { - foreach (var element in Items.OfType()) - { - element.Validate(); - } - } - } } } diff --git a/src/KubernetesClient/Models/ModelVersionConverter.cs b/src/KubernetesClient/Models/ModelVersionConverter.cs deleted file mode 100644 index e48f39787..000000000 --- a/src/KubernetesClient/Models/ModelVersionConverter.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace k8s.Models; - -public static class ModelVersionConverter -{ - public interface IModelVersionConverter - { - TTo Convert(TFrom from); - } - - public static IModelVersionConverter Converter { get; set; } - - internal static TTo Convert(TFrom from) - { - if (Converter == null) - { - throw new InvalidOperationException("Converter is not set"); - } - - return Converter.Convert(from); - } -} diff --git a/src/KubernetesClient/Models/ResourceQuantity.cs b/src/KubernetesClient/Models/ResourceQuantity.cs index 2d1a4898d..6b4ff8d88 100644 --- a/src/KubernetesClient/Models/ResourceQuantity.cs +++ b/src/KubernetesClient/Models/ResourceQuantity.cs @@ -54,7 +54,7 @@ namespace k8s.Models /// cause implementors to also use a fixed point implementation. /// [JsonConverter(typeof(ResourceQuantityJsonConverter))] - public partial class ResourceQuantity + public struct ResourceQuantity { public enum SuffixFormat { @@ -97,39 +97,6 @@ public override string ToString() return CanonicalizeString(); } - protected bool Equals(ResourceQuantity other) - { - return _unitlessValue.Equals(other?._unitlessValue); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - if (obj.GetType() != GetType()) - { - return false; - } - - return Equals((ResourceQuantity)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((int)Format * 397) ^ _unitlessValue.GetHashCode(); - } - } - // // CanonicalizeString = go version CanonicalizeBytes // CanonicalizeBytes returns the canonical form of q and its suffix (see comment on Quantity). @@ -157,10 +124,9 @@ public string CanonicalizeString(SuffixFormat suffixFormat) return Suffixer.AppendMaxSuffix(_unitlessValue, suffixFormat); } - // ctor - partial void CustomInit() + public ResourceQuantity(string v) { - if (Value == null) + if (v == null) { // No value has been defined, initialize to 0. _unitlessValue = new Fraction(0); @@ -168,7 +134,7 @@ partial void CustomInit() return; } - var value = Value.Trim(); + var value = v.Trim(); var si = value.IndexOfAny(SuffixChars); if (si == -1) @@ -188,6 +154,11 @@ partial void CustomInit() } } + public static implicit operator ResourceQuantity(string v) + { + return new ResourceQuantity(v); + } + private static bool HasMantissa(Fraction value) { if (value.IsZero) @@ -200,7 +171,7 @@ private static bool HasMantissa(Fraction value) public static implicit operator decimal(ResourceQuantity v) { - return v?.ToDecimal() ?? 0; + return v.ToDecimal(); } public static implicit operator ResourceQuantity(decimal v) diff --git a/src/KubernetesClient/Models/ResourceQuantityJsonConverter.cs b/src/KubernetesClient/Models/ResourceQuantityJsonConverter.cs index 613208679..a99eb334b 100644 --- a/src/KubernetesClient/Models/ResourceQuantityJsonConverter.cs +++ b/src/KubernetesClient/Models/ResourceQuantityJsonConverter.cs @@ -8,16 +8,16 @@ public override ResourceQuantity Read(ref Utf8JsonReader reader, Type typeToConv switch (reader.TokenType) { case JsonTokenType.Null: - return new ResourceQuantity(null); + return null; case JsonTokenType.Number: if (reader.TryGetDouble(out var val)) { - return new ResourceQuantity(Convert.ToString(val)); + return Convert.ToString(val); } return reader.GetDecimal(); default: - return new ResourceQuantity(reader.GetString()); + return reader.GetString(); } } @@ -28,7 +28,7 @@ public override void Write(Utf8JsonWriter writer, ResourceQuantity value, JsonSe throw new ArgumentNullException(nameof(writer)); } - writer.WriteStringValue(value?.ToString()); + writer.WriteStringValue(value.ToString()); } } } diff --git a/src/KubernetesClient/Models/ResourceQuantityYamlConverter.cs b/src/KubernetesClient/Models/ResourceQuantityYamlConverter.cs index ce0ec8e54..50523ca6e 100644 --- a/src/KubernetesClient/Models/ResourceQuantityYamlConverter.cs +++ b/src/KubernetesClient/Models/ResourceQuantityYamlConverter.cs @@ -21,7 +21,7 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria return null; } - return new ResourceQuantity(scalar?.Value); + return scalar?.Value; } finally { @@ -35,7 +35,7 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer) { var obj = (ResourceQuantity)value; - emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj?.ToString())); + emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj.ToString())); } } } diff --git a/src/KubernetesClient/Models/V1Patch.cs b/src/KubernetesClient/Models/V1Patch.cs index 4f8f44c50..5838e4b05 100644 --- a/src/KubernetesClient/Models/V1Patch.cs +++ b/src/KubernetesClient/Models/V1Patch.cs @@ -1,7 +1,7 @@ namespace k8s.Models { [JsonConverter(typeof(V1PatchJsonConverter))] - public partial class V1Patch + public record V1Patch { public enum PatchType { @@ -31,26 +31,21 @@ public enum PatchType ApplyPatch, } + [JsonPropertyName("content")] + [JsonInclude] + public object Content { get; private set; } + public PatchType Type { get; private set; } public V1Patch(object body, PatchType type) { - Content = body; - Type = type; - CustomInit(); - } - - partial void CustomInit() - { - if (Content == null) + if (type == PatchType.Unknown) { - throw new ArgumentNullException(nameof(Content), "object must be set"); + throw new ArgumentException("patch type must be set", nameof(type)); } - if (Type == PatchType.Unknown) - { - throw new ArgumentException("patch type must be set", nameof(Type)); - } + Content = body ?? throw new ArgumentNullException(nameof(body), "object must be set"); + Type = type; } } } diff --git a/src/KubernetesClient/Models/V1PodTemplateSpec.cs b/src/KubernetesClient/Models/V1PodTemplateSpec.cs index 0462b5373..4efa3cdbb 100644 --- a/src/KubernetesClient/Models/V1PodTemplateSpec.cs +++ b/src/KubernetesClient/Models/V1PodTemplateSpec.cs @@ -4,7 +4,7 @@ namespace k8s.Models /// Partial implementation of the IMetadata interface /// to open this class up to ModelExtensions methods /// - public partial class V1PodTemplateSpec : IMetadata + public partial record V1PodTemplateSpec : IMetadata { } } diff --git a/src/KubernetesClient/Models/V1Status.ObjectView.cs b/src/KubernetesClient/Models/V1Status.ObjectView.cs index 6f5a1ae85..aab834a95 100644 --- a/src/KubernetesClient/Models/V1Status.ObjectView.cs +++ b/src/KubernetesClient/Models/V1Status.ObjectView.cs @@ -1,6 +1,6 @@ namespace k8s.Models { - public partial class V1Status + public partial record V1Status { internal sealed class V1StatusObjectViewConverter : JsonConverter { diff --git a/src/KubernetesClient/Models/V1Status.cs b/src/KubernetesClient/Models/V1Status.cs index 87e4be055..d69116d2e 100644 --- a/src/KubernetesClient/Models/V1Status.cs +++ b/src/KubernetesClient/Models/V1Status.cs @@ -2,7 +2,7 @@ namespace k8s.Models { - public partial class V1Status + public partial record V1Status { /// Converts a object into a short description of the status. /// string description of the status diff --git a/src/LibKubernetesGenerator/ClassNameHelper.cs b/src/LibKubernetesGenerator/ClassNameHelper.cs index a307a160f..a3b012f29 100644 --- a/src/LibKubernetesGenerator/ClassNameHelper.cs +++ b/src/LibKubernetesGenerator/ClassNameHelper.cs @@ -78,6 +78,12 @@ public string GetClassNameForSchemaDefinition(JsonSchema definition) } + if (definition.Format == "int-or-string") + { + return "IntOrString"; + } + + return schemaToNameMapCooked[definition]; } } diff --git a/src/LibKubernetesGenerator/GeneralNameHelper.cs b/src/LibKubernetesGenerator/GeneralNameHelper.cs index 15194bb90..2d4f646f7 100644 --- a/src/LibKubernetesGenerator/GeneralNameHelper.cs +++ b/src/LibKubernetesGenerator/GeneralNameHelper.cs @@ -57,8 +57,6 @@ private string GetInterfaceName(JsonSchema definition) } } - interfaces.Add("IValidate"); - return string.Join(", ", interfaces); } @@ -68,7 +66,7 @@ public string GetDotNetNameOpenApiParameter(OpenApiParameter parameter, string i if (init == "true" && !parameter.IsRequired) { - name += " = null"; + name += " = default"; } return name; diff --git a/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs b/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs index 7adf6ef1d..fd2713260 100644 --- a/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs +++ b/src/LibKubernetesGenerator/KubernetesClientSourceGenerator.cs @@ -58,12 +58,10 @@ private static IContainer BuildContainer(OpenApiDocument swagger) builder.RegisterType() ; - builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); builder.RegisterType(); - builder.RegisterType(); builder.RegisterType(); return builder.Build(); @@ -79,9 +77,7 @@ public void Initialize(IncrementalGeneratorInitializationContext generatorContex container.Resolve().Generate(swagger, ctx); container.Resolve().Generate(swagger, ctx); - container.Resolve().Generate(swagger, ctx); container.Resolve().Generate(swagger, ctx); - container.Resolve().Generate(swagger, ctx); container.Resolve().Generate(swagger, ctx); container.Resolve().Generate(swagger, ctx); }); diff --git a/src/LibKubernetesGenerator/ModelExtGenerator.cs b/src/LibKubernetesGenerator/ModelExtGenerator.cs deleted file mode 100644 index bbadcb5c0..000000000 --- a/src/LibKubernetesGenerator/ModelExtGenerator.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.CodeAnalysis; -using NSwag; -using System.Collections.Generic; -using System.Linq; - -namespace LibKubernetesGenerator -{ - internal class ModelExtGenerator - { - private readonly ClassNameHelper classNameHelper; - private readonly ScriptObjectFactory scriptObjectFactory; - - public ModelExtGenerator(ClassNameHelper classNameHelper, ScriptObjectFactory scriptObjectFactory) - { - this.classNameHelper = classNameHelper; - this.scriptObjectFactory = scriptObjectFactory; - } - - public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context) - { - // Generate the interface declarations - var skippedTypes = new HashSet { "V1WatchEvent" }; - - var definitions = swagger.Definitions.Values - .Where( - d => d.ExtensionData != null - && d.ExtensionData.ContainsKey("x-kubernetes-group-version-kind") - && !skippedTypes.Contains(classNameHelper.GetClassName(d))); - - var sc = scriptObjectFactory.CreateScriptObject(); - sc.SetValue("definitions", definitions, true); - - context.RenderToContext("ModelExtensions.cs.template", sc, "ModelExtensions.g.cs"); - } - } -} diff --git a/src/LibKubernetesGenerator/ModelGenerator.cs b/src/LibKubernetesGenerator/ModelGenerator.cs index 98b9576cd..df9f8d3ea 100644 --- a/src/LibKubernetesGenerator/ModelGenerator.cs +++ b/src/LibKubernetesGenerator/ModelGenerator.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Microsoft.CodeAnalysis; using NSwag; @@ -18,15 +19,49 @@ public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializa { var sc = scriptObjectFactory.CreateScriptObject(); + var genSkippedTypes = new HashSet + { + "IntOrString", + "ResourceQuantity", + "V1Patch", + }; + + var extSkippedTypes = new HashSet + { + "V1WatchEvent", + }; + + var typeOverrides = new Dictionary + { + // not used at the moment + }; foreach (var kv in swagger.Definitions) { var def = kv.Value; var clz = classNameHelper.GetClassNameForSchemaDefinition(def); + if (genSkippedTypes.Contains(clz)) + { + continue; + } + + var hasExt = def.ExtensionData != null + && def.ExtensionData.ContainsKey("x-kubernetes-group-version-kind") + && !extSkippedTypes.Contains(clz); + + + var typ = "record"; + if (typeOverrides.TryGetValue(clz, out var to)) + { + typ = to; + } + sc.SetValue("clz", clz, true); sc.SetValue("def", def, true); sc.SetValue("properties", def.Properties.Values, true); + sc.SetValue("typ", typ, true); + sc.SetValue("hasExt", hasExt, true); context.RenderToContext("Model.cs.template", sc, $"Models_{clz}.g.cs"); } diff --git a/src/LibKubernetesGenerator/VersionConverterStubGenerator.cs b/src/LibKubernetesGenerator/VersionConverterStubGenerator.cs deleted file mode 100644 index 58550006d..000000000 --- a/src/LibKubernetesGenerator/VersionConverterStubGenerator.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; -using NSwag; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace LibKubernetesGenerator -{ - internal class VersionConverterStubGenerator - { - private readonly ClassNameHelper classNameHelper; - - public VersionConverterStubGenerator(ClassNameHelper classNameHelper) - { - this.classNameHelper = classNameHelper; - } - - public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context) - { - var allGeneratedModelClassNames = new List(); - - foreach (var kv in swagger.Definitions) - { - var def = kv.Value; - var clz = classNameHelper.GetClassNameForSchemaDefinition(def); - allGeneratedModelClassNames.Add(clz); - } - - var versionRegex = @"(^V|v)[0-9]+((alpha|beta)[0-9]+)?"; - var typePairs = allGeneratedModelClassNames - .OrderBy(x => x) - .Select(x => new - { - Version = Regex.Match(x, versionRegex).Value?.ToLower(), - Kinda = Regex.Replace(x, versionRegex, string.Empty), - Type = x, - }) - .Where(x => !string.IsNullOrEmpty(x.Version)) - .GroupBy(x => x.Kinda) - .Where(x => x.Count() > 1) - .SelectMany(x => - x.SelectMany((value, index) => x.Skip(index + 1), (first, second) => new { first, second })) - .OrderBy(x => x.first.Kinda) - .ThenBy(x => x.first.Version) - .Select(x => (x.first.Type, x.second.Type)) - .ToList(); - - var sbmodel = new StringBuilder(@"// -namespace k8s.Models; -"); - - foreach (var (t0, t1) in typePairs) - { - sbmodel.AppendLine($@" - public partial class {t0} - {{ - public static explicit operator {t0}({t1} s) => ModelVersionConverter.Convert<{t1}, {t0}>(s); - }} - public partial class {t1} - {{ - public static explicit operator {t1}({t0} s) => ModelVersionConverter.Convert<{t0}, {t1}>(s); - }}"); - } - - context.AddSource($"ModelOperators.g.cs", SourceText.From(sbmodel.ToString(), Encoding.UTF8)); - } - } -} diff --git a/src/LibKubernetesGenerator/templates/Model.cs.template b/src/LibKubernetesGenerator/templates/Model.cs.template index 42e0bd0e6..721709f1e 100644 --- a/src/LibKubernetesGenerator/templates/Model.cs.template +++ b/src/LibKubernetesGenerator/templates/Model.cs.template @@ -4,92 +4,29 @@ // regenerated. // -namespace k8s.Models +namespace k8s.Models; + +/// +/// {{ToXmlDoc def.description}} +/// +{{ if hasExt }} +[KubernetesEntity(Group=KubeGroup, Kind=KubeKind, ApiVersion=KubeApiVersion, PluralName=KubePluralName)] +{{ end }} +public partial {{typ}} {{clz}} {{ if hasExt }} : {{ GetInterfaceName def }} {{ end }} { + {{ if hasExt}} + public const string KubeApiVersion = "{{ GetApiVersion def }}"; + public const string KubeKind = "{{ GetKind def }}"; + public const string KubeGroup = "{{ GetGroup def }}"; + public const string KubePluralName = "{{ GetPlural def }}"; + {{ end }} + + {{ for property in properties }} /// - /// {{ToXmlDoc def.description}} + /// {{ToXmlDoc property.description}} /// - public partial class {{clz}} - { - /// - /// Initializes a new instance of the {{GetClassName def}} class. - /// - public {{clz}}() - { - CustomInit(); - } - - /// - /// Initializes a new instance of the {{GetClassName def}} class. - /// - {{ for property in properties }} - {{ if property.IsRequired }} - /// - /// {{ToXmlDoc property.description}} - /// - {{ end }} - {{ end }} - - {{ for property in properties }} - {{ if !property.IsRequired }} - /// - /// {{ToXmlDoc property.description}} - /// - {{ end }} - {{ end }} - public {{clz}}({{GetModelCtorParam def}}) - { - {{ for property in properties }} - {{GetDotNetName property.name "field"}} = {{GetDotNetName property.name "fieldctor"}}; - {{ end }} - CustomInit(); - } - - /// - /// An initialization method that performs custom operations like setting defaults - /// - partial void CustomInit(); - - {{ for property in properties }} - /// - /// {{ToXmlDoc property.description}} - /// - [JsonPropertyName("{{property.name}}")] - public {{GetDotNetType property}} {{GetDotNetName property.name "field"}} { get; set; } - {{ end }} - - /// - /// Validate the object. - /// - - public virtual void Validate() - { - {{ for property in properties }} - {{if IfType property "object" }} - {{ if property.IsRequired }} - if ({{GetDotNetName property.name "field"}} == null) - { - throw new ArgumentNullException("{{GetDotNetName property.name "field"}}"); - } - {{ end }} - {{ end }} - - {{ end }} - - {{ for property in properties }} - {{if IfType property "object" }} - {{GetDotNetName property.name "field"}}?.Validate(); - {{ end }} - - {{if IfType property "objectarray" }} - if ({{GetDotNetName property.name "field"}} != null){ - foreach(var obj in {{GetDotNetName property.name "field"}}) - { - obj.Validate(); - } - } - {{ end }} - {{ end }} - } - } + [JsonPropertyName("{{property.name}}")] + public {{ if property.IsRequired }} required {{ end }} {{GetDotNetType property}} {{GetDotNetName property.name "field"}} { get; set; } + {{ end }} } + diff --git a/src/LibKubernetesGenerator/templates/ModelExtensions.cs.template b/src/LibKubernetesGenerator/templates/ModelExtensions.cs.template deleted file mode 100644 index d52a3e714..000000000 --- a/src/LibKubernetesGenerator/templates/ModelExtensions.cs.template +++ /dev/null @@ -1,17 +0,0 @@ -// -// Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator -// Changes may cause incorrect behavior and will be lost if the code is regenerated. -// -namespace k8s.Models -{ -{{ for definition in definitions }} - [KubernetesEntity(Group=KubeGroup, Kind=KubeKind, ApiVersion=KubeApiVersion, PluralName=KubePluralName)] - public partial class {{ GetClassName definition }} : {{ GetInterfaceName definition }} - { - public const string KubeApiVersion = "{{ GetApiVersion definition }}"; - public const string KubeKind = "{{ GetKind definition }}"; - public const string KubeGroup = "{{ GetGroup definition }}"; - public const string KubePluralName = "{{ GetPlural definition }}"; - } -{{ end }} -} diff --git a/tests/E2E.Aot.Tests/MinikubeTests.cs b/tests/E2E.Aot.Tests/MinikubeTests.cs index 505d9a4b2..4fd4ed044 100644 --- a/tests/E2E.Aot.Tests/MinikubeTests.cs +++ b/tests/E2E.Aot.Tests/MinikubeTests.cs @@ -172,27 +172,33 @@ public async Task DatetimeFieldTest() using var kubernetes = CreateClient(); await kubernetes.CoreV1.CreateNamespacedEventAsync( - new Corev1Event( - new V1ObjectReference( - "v1alpha1", - kind: "Test", - name: "test", - namespaceProperty: "default", - resourceVersion: "1", - uid: "1"), - new V1ObjectMeta() + new Corev1Event + { + InvolvedObject = new V1ObjectReference + { + ApiVersion = "v1alpha1", + Kind = "Test", + Name = "test", + NamespaceProperty = "default", + ResourceVersion = "1", + Uid = "1", + }, + Metadata = new V1ObjectMeta { GenerateName = "started-", }, - action: "STARTED", - type: "Normal", - reason: "STARTED", - message: "Started", - eventTime: DateTime.Now, - firstTimestamp: DateTime.Now, - lastTimestamp: DateTime.Now, - reportingComponent: "37", - reportingInstance: "38"), "default").ConfigureAwait(false); + Action = "STARTED", + Type = "Normal", + Reason = "STARTED", + Message = "Started", + EventTime = DateTime.Now, + FirstTimestamp = DateTime.Now, + LastTimestamp = DateTime.Now, + ReportingComponent = "37", + ReportingInstance = "38", + }, + "default" + ).ConfigureAwait(false); } [MinikubeFact] diff --git a/tests/E2E.Tests/MinikubeTests.cs b/tests/E2E.Tests/MinikubeTests.cs index 547ee90ea..a04141c77 100644 --- a/tests/E2E.Tests/MinikubeTests.cs +++ b/tests/E2E.Tests/MinikubeTests.cs @@ -451,27 +451,33 @@ public async Task DatetimeFieldTest() using var kubernetes = CreateClient(); await kubernetes.CoreV1.CreateNamespacedEventAsync( - new Corev1Event( - new V1ObjectReference( - "v1alpha1", - kind: "Test", - name: "test", - namespaceProperty: "default", - resourceVersion: "1", - uid: "1"), - new V1ObjectMeta() + new Corev1Event + { + Metadata = new V1ObjectMeta { GenerateName = "started-", + NamespaceProperty = "default", + }, + InvolvedObject = new V1ObjectReference + { + ApiVersion = "v1alpha1", + Kind = "Test", + Name = "test", + NamespaceProperty = "default", + ResourceVersion = "1", + Uid = "1", }, - action: "STARTED", - type: "Normal", - reason: "STARTED", - message: "Started", - eventTime: DateTime.Now, - firstTimestamp: DateTime.Now, - lastTimestamp: DateTime.Now, - reportingComponent: "37", - reportingInstance: "38"), "default").ConfigureAwait(false); + Action = "STARTED", + Type = "Normal", + Reason = "STARTED", + Message = "Started", + EventTime = DateTime.Now, + FirstTimestamp = DateTime.Now, + LastTimestamp = DateTime.Now, + ReportingComponent = "37", + ReportingInstance = "38", + }, + "default").ConfigureAwait(false); } [MinikubeFact] diff --git a/tests/KubernetesClient.Classic.Tests/SimpleTests.cs b/tests/KubernetesClient.Classic.Tests/SimpleTests.cs index f0437defb..3e17a5854 100644 --- a/tests/KubernetesClient.Classic.Tests/SimpleTests.cs +++ b/tests/KubernetesClient.Classic.Tests/SimpleTests.cs @@ -7,7 +7,7 @@ namespace k8s.tests; -public class BasicTests +public class SimpleTests { // TODO: fail to setup asp.net core 6 on net48 private class DummyHttpServer : System.IDisposable diff --git a/tests/KubernetesClient.Tests/IntOrStringTests.cs b/tests/KubernetesClient.Tests/IntOrStringTests.cs index 9fb3415a5..281308b1f 100644 --- a/tests/KubernetesClient.Tests/IntOrStringTests.cs +++ b/tests/KubernetesClient.Tests/IntOrStringTests.cs @@ -10,13 +10,13 @@ public void Serialize() { { var v = 123; - IntstrIntOrString intorstr = v; + IntOrString intorstr = v; Assert.Equal("123", KubernetesJson.Serialize(intorstr)); } { - IntstrIntOrString intorstr = "12%"; + IntOrString intorstr = "12%"; Assert.Equal("\"12%\"", KubernetesJson.Serialize(intorstr)); } } @@ -25,12 +25,12 @@ public void Serialize() public void Deserialize() { { - var v = KubernetesJson.Deserialize("1234"); + var v = KubernetesJson.Deserialize("1234"); Assert.Equal("1234", v.Value); } { - var v = KubernetesJson.Deserialize("\"12%\""); + var v = KubernetesJson.Deserialize("\"12%\""); Assert.Equal("12%", v.Value); } } diff --git a/tests/KubernetesClient.Tests/KubernetesYamlTests.cs b/tests/KubernetesClient.Tests/KubernetesYamlTests.cs index 19b03fdaa..1b18f5493 100644 --- a/tests/KubernetesClient.Tests/KubernetesYamlTests.cs +++ b/tests/KubernetesClient.Tests/KubernetesYamlTests.cs @@ -33,7 +33,7 @@ public void LoadAllFromString() } #pragma warning disable CA1812 // Class is used for YAML deserialization tests - private class MyPod : V1Pod + private record MyPod : V1Pod { } #pragma warning restore CA1812 @@ -531,7 +531,7 @@ public void SerializeIntOrString() var obj = new V1Service { Kind = "Service", - Metadata = new V1ObjectMeta(labels: labels, name: "test-svc"), + Metadata = new V1ObjectMeta { Name = "test-svc", Labels = labels }, ApiVersion = "v1", Spec = new V1ServiceSpec {