Support round-trip CRD (de)serialization (#1034)

* Support round-trip CRD (de)serialization

* Add a floating point emitter to fix UT

* Unused using

* Stylecop

* Reduce warnings
This commit is contained in:
stan-sz
2022-09-27 10:01:51 +02:00
committed by GitHub
parent dec73d412a
commit bbd3b6cd50
4 changed files with 85 additions and 1 deletions

View File

@@ -0,0 +1,32 @@
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.EventEmitters;
namespace k8s
{
internal class FloatEmitter : ChainedEventEmitter
{
public FloatEmitter(IEventEmitter nextEmitter)
: base(nextEmitter)
{
}
public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter)
{
switch (eventInfo.Source.Value)
{
// Floating point numbers should always render at least one zero (e.g. 1.0f => '1.0' not '1')
case double d:
emitter.Emit(new Scalar(d.ToString("0.0######################")));
break;
case float f:
emitter.Emit(new Scalar(f.ToString("0.0######################")));
break;
default:
base.Emit(eventInfo, emitter);
break;
}
}
}
}

View File

@@ -21,6 +21,7 @@ namespace k8s
.WithTypeConverter(new IntOrStringYamlConverter())
.WithTypeConverter(new ByteArrayStringYamlConverter())
.WithTypeConverter(new ResourceQuantityYamlConverter())
.WithAttemptingUnquotedStringTypeDeserialization()
.WithOverridesFromJsonPropertyAttributes()
.IgnoreUnmatchedProperties()
.Build();
@@ -33,6 +34,7 @@ namespace k8s
.WithTypeConverter(new ByteArrayStringYamlConverter())
.WithTypeConverter(new ResourceQuantityYamlConverter())
.WithEventEmitter(e => new StringQuotingEmitter(e))
.WithEventEmitter(e => new FloatEmitter(e))
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull)
.WithOverridesFromJsonPropertyAttributes()
.BuildValueSerializer();

View File

@@ -104,7 +104,6 @@ namespace k8s
{
cert = new X509Certificate2(cert.Export(X509ContentType.Pkcs12));
}
}
return cert;

View File

@@ -841,5 +841,56 @@ spec:
var ver = result.Spec.Versions[0];
Assert.Equal(true, ver?.Schema?.OpenAPIV3Schema?.XKubernetesIntOrString);
}
#pragma warning disable CA1812 // Class is used for YAML deserialization tests
[KubernetesEntity(Group = KubeGroup, Kind = KubeKind, ApiVersion = KubeApiVersion, PluralName = KubePluralName)]
private sealed class V1AlphaFoo : IKubernetesObject<V1ObjectMeta>, ISpec<Dictionary<string, object>>
{
public const string KubeApiVersion = "v1alpha";
public const string KubeKind = "foo";
public const string KubeGroup = "foo.bar";
public const string KubePluralName = "foos";
public string ApiVersion { get; set; }
public string Kind { get; set; }
public V1ObjectMeta Metadata { get; set; }
public Dictionary<string, object> Spec { get; set; }
public V1AlphaFoo()
{
Metadata = new V1ObjectMeta();
Spec = new Dictionary<string, object>();
}
}
#pragma warning restore CA1812 // Class is used for YAML deserialization tests
[Fact]
public void LoadAllFromStringWithTypeMapGenericCRD()
{
var content = @"apiVersion: foo.bar/v1alpha
kind: Foo
metadata:
name: foo
namespace: ns
spec:
bool: false
byte: 123
float: 12.0
";
var objs = KubernetesYaml.LoadAllFromString(content, new Dictionary<string, Type>
{
{ $"{V1AlphaFoo.KubeGroup}/{V1AlphaFoo.KubeApiVersion}/Foo", typeof(V1AlphaFoo) },
});
Assert.Single(objs);
var v1AlphaFoo = Assert.IsType<V1AlphaFoo>(objs[0]);
Assert.Equal("foo", v1AlphaFoo.Metadata.Name);
Assert.Equal("ns", v1AlphaFoo.Metadata.NamespaceProperty);
Assert.Equal(3, v1AlphaFoo.Spec.Count);
Assert.False(Assert.IsType<bool>(v1AlphaFoo.Spec["bool"]));
Assert.Equal(123, Assert.IsType<byte>(v1AlphaFoo.Spec["byte"]));
Assert.Equal(12.0, Assert.IsType<float>(v1AlphaFoo.Spec["float"]), 3);
Assert.Equal(content.Replace("\r\n", "\n"), KubernetesYaml.SerializeAll(objs).Replace("\r\n", "\n"));
}
}
}