From ecdb22d790a1f7debee024928cda155ec316bd82 Mon Sep 17 00:00:00 2001 From: Jerome Haltom Date: Sat, 4 Jan 2025 18:33:46 -0600 Subject: [PATCH] Properly get attributes. Remove EnumMember. STJ doesn't actually use this. Add a unit test. Test in .NET 9. Unsure if author wants to test both 8 and 9. --- src/KubeOps.Transpiler/Crds.cs | 25 ++++++++++--------- src/KubeOps.Transpiler/Utilities.cs | 12 +++++++++ test/Directory.Build.props | 2 +- test/KubeOps.Transpiler.Test/Crds.Mlc.Test.cs | 23 +++++++++++++++++ 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/KubeOps.Transpiler/Crds.cs b/src/KubeOps.Transpiler/Crds.cs index 40b924f7..2f24d433 100644 --- a/src/KubeOps.Transpiler/Crds.cs +++ b/src/KubeOps.Transpiler/Crds.cs @@ -345,35 +345,36 @@ private static V1JSONSchemaProps Map(this MetadataLoadContext context, Type type private static IList GetEnumNames(this MetadataLoadContext context, Type type) { +#if NET9_0_OR_GREATER var attributeNameByFieldName = new Dictionary(); + foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static)) { - if (field.GetCustomAttribute() is { Value: not null } enumMemberAtribute) - { - attributeNameByFieldName.Add(field.Name, enumMemberAtribute.Value); - } -#if NET9_0_OR_GREATER - if (field.GetCustomAttribute() is { Name: not null } jsonMemberNameAtribute) + if (field.GetCustomAttributeData() is { } jsonMemberNameAttribute && + jsonMemberNameAttribute.GetCustomAttributeCtorArg(context, 0) is { } jsonMemberNameAtributeName) { - attributeNameByFieldName.Add(field.Name, jsonMemberNameAtribute.Name); + attributeNameByFieldName.Add(field.Name, jsonMemberNameAtributeName); } -#endif } - var enumName = new List(); + var enumNames = new List(); + foreach (var value in Enum.GetNames(type)) { if (attributeNameByFieldName.TryGetValue(value, out var name)) { - enumName.Add(name); + enumNames.Add(name); } else { - enumName.Add(value); + enumNames.Add(value); } } - return enumName; + return enumNames; +#else + return Enum.GetNames(type); +#endif } private static V1JSONSchemaProps MapObjectType(this MetadataLoadContext context, Type type) diff --git a/src/KubeOps.Transpiler/Utilities.cs b/src/KubeOps.Transpiler/Utilities.cs index 67c97ee2..8593a40b 100644 --- a/src/KubeOps.Transpiler/Utilities.cs +++ b/src/KubeOps.Transpiler/Utilities.cs @@ -20,6 +20,18 @@ public static class Utilities .GetCustomAttributes(type) .FirstOrDefault(a => a.AttributeType.Name == typeof(TAttribute).Name); + /// + /// Load a custom attribute from a read-only-reflected field. + /// + /// The field. + /// The type of the attribute to load. + /// The custom attribute data if an attribute is found. + public static CustomAttributeData? GetCustomAttributeData(this FieldInfo field) + where TAttribute : Attribute + => CustomAttributeData + .GetCustomAttributes(field) + .FirstOrDefault(a => a.AttributeType.Name == typeof(TAttribute).Name); + /// /// Load a custom attribute from a read-only-reflected property. /// diff --git a/test/Directory.Build.props b/test/Directory.Build.props index bcea30f7..1c833b76 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -1,6 +1,6 @@ - net8.0 + net9.0 enable enable false diff --git a/test/KubeOps.Transpiler.Test/Crds.Mlc.Test.cs b/test/KubeOps.Transpiler.Test/Crds.Mlc.Test.cs index 17a72d2f..d31f4662 100644 --- a/test/KubeOps.Transpiler.Test/Crds.Mlc.Test.cs +++ b/test/KubeOps.Transpiler.Test/Crds.Mlc.Test.cs @@ -40,6 +40,7 @@ public class CrdsMlcTest(MlcProvider provider) : TranspilerTestBase(provider) [InlineData(typeof(SetIntEntity), "array", null, false)] [InlineData(typeof(InheritedEnumerableEntity), "array", null, false)] [InlineData(typeof(EnumEntity), "string", null, false)] + [InlineData(typeof(NamedEnumEntity), "string", null, false)] [InlineData(typeof(NullableEnumEntity), "string", null, true)] [InlineData(typeof(DictionaryEntity), "object", null, false)] [InlineData(typeof(EnumerableKeyPairsEntity), "object", null, false)] @@ -475,6 +476,14 @@ public void Should_Correctly_Use_Entity_Scope_Attribute() clusterCrd.Spec.Scope.Should().Be("Cluster"); } + [Fact] + public void Should_Correctly_Get_Enum_Value_From_JsonStringEnumMemberNameAttribute() + { + var crd = _mlc.Transpile(typeof(NamedEnumEntity)); + var specProperties = crd.Spec.Versions.First().Schema.OpenAPIV3Schema.Properties["property"]; + specProperties.EnumProperty.Should().BeEquivalentTo(["enumValue1", "enumValue2"]); + } + #region Test Entity Classes [KubernetesEntity(Group = "testing.dev", ApiVersion = "v1", Kind = "TestEntity")] @@ -659,6 +668,20 @@ public enum TestSpecEnum } } + [KubernetesEntity(Group = "testing.dev", ApiVersion = "v1", Kind = "TestEntity")] + private class NamedEnumEntity : CustomKubernetesEntity + { + public TestSpecEnum Property { get; set; } + + public enum TestSpecEnum + { + [JsonStringEnumMemberName("enumValue1")] + Value1, + [JsonStringEnumMemberName("enumValue2")] + Value2, + } + } + [KubernetesEntity(Group = "testing.dev", ApiVersion = "v1", Kind = "TestEntity")] private class SimpleDictionaryEntity : CustomKubernetesEntity {