Browse Source

Fix for issue #207 (#237)

* Created a object graph visitor to ignore also empty collections on serialization. Unify creation of serilizer/deserialization objects with specified configuration

* Update OmitDefaultAndEmptyArrayObjectGraphVisitor.cs

* Update YamlSerializer.cs

* Fix tests with EOL issues on different SO #235

Co-authored-by: Justin Kotalik <jkotalik12@gmail.com>
pull/242/head
Unai Zorrilla 6 years ago
committed by GitHub
parent
commit
decc50afbc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      src/Microsoft.Tye.Core/ConfigModel/ConfigFactory.cs
  2. 46
      src/Microsoft.Tye.Core/Serialization/OmitDefaultAndEmptyArrayObjectGraphVisitor.cs
  3. 28
      src/Microsoft.Tye.Core/Serialization/YamlSerializer.cs
  4. 11
      src/tye/InitHost.cs
  5. 12
      test/E2ETest/Infrastructure/StringExtensions.cs
  6. 10
      test/E2ETest/TyeGenerateTests.cs
  7. 7
      test/E2ETest/TyeInitTests.cs

7
src/Microsoft.Tye.Core/ConfigModel/ConfigFactory.cs

@ -4,8 +4,7 @@
using System.Collections.Generic;
using System.IO;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using Microsoft.Tye.Serialization;
namespace Microsoft.Tye.ConfigModel
{
@ -75,9 +74,7 @@ namespace Microsoft.Tye.ConfigModel
private static ConfigApplication FromYaml(FileInfo file)
{
var deserializer = new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var deserializer = YamlSerializer.CreateDeserializer();
using var reader = file.OpenText();
var application = deserializer.Deserialize<ConfigApplication>(reader);

46
src/Microsoft.Tye.Core/Serialization/OmitDefaultAndEmptyArrayObjectGraphVisitor.cs

@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.ObjectGraphVisitors;
namespace Microsoft.Tye.Serialization
{
internal sealed class OmitDefaultAndEmptyArrayObjectGraphVisitor
: ChainedObjectGraphVisitor
{
public OmitDefaultAndEmptyArrayObjectGraphVisitor(IObjectGraphVisitor<IEmitter> nextVisitor)
: base(nextVisitor) { }
private static object? GetDefault(Type type)
{
return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) : null;
}
private static bool IsEmptyArray(Type type, object? value)
{
return value is object
&& value is ICollection
&& ((ICollection)value).Count == 0;
}
public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context)
{
var defaultValueAttribute = key.GetCustomAttribute<DefaultValueAttribute>();
var defaultValue = defaultValueAttribute != null
? defaultValueAttribute.Value
: GetDefault(key.Type);
return !Equals(value.Value, defaultValue)
&& !IsEmptyArray(value.Type, value.Value)
&& base.EnterMapping(key, value, context);
}
}
}

28
src/Microsoft.Tye.Core/Serialization/YamlSerializer.cs

@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace Microsoft.Tye.Serialization
{
public static class YamlSerializer
{
public static ISerializer CreateSerializer()
{
return new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults)
.WithEmissionPhaseObjectGraphVisitor(args => new OmitDefaultAndEmptyArrayObjectGraphVisitor(args.InnerVisitor))
.Build();
}
public static IDeserializer CreateDeserializer()
{
return new DeserializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
}
}
}

11
src/tye/InitHost.cs

@ -1,14 +1,11 @@
using System.IO;
using Microsoft.Tye.ConfigModel;
using Microsoft.Tye.Hosting.Dashboard;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using Microsoft.Tye.Serialization;
namespace Microsoft.Tye
{
public class InitHost
{
public static string CreateTyeFile(FileInfo? path, bool force)
{
var (content, outputFilePath) = CreateTyeFileContent(path, force);
@ -58,10 +55,7 @@ services:
if (path is FileInfo && path.Exists)
{
var application = ConfigFactory.FromFile(path);
var serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults)
.Build();
var serializer = YamlSerializer.CreateSerializer();
var extension = path.Extension.ToLowerInvariant();
var directory = path.Directory;
@ -106,7 +100,6 @@ services:
return (template, outputFilePath);
}
private static void ThrowIfTyeFilePresent(FileInfo? path, string yml)
{
var tyeYaml = Path.Combine(path!.DirectoryName, yml);

12
test/E2ETest/Infrastructure/StringExtensions.cs

@ -0,0 +1,12 @@
namespace System
{
internal static class StringExtensions
{
public static string NormalizeNewLines(this string value)
{
return value
.Replace("\r\n", "\n")
.Replace("\n", Environment.NewLine);
}
}
}

10
test/E2ETest/TyeGenerateTests.cs

@ -2,10 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Tye;
using Microsoft.Tye.ConfigModel;
using Xunit;
using Xunit.Abstractions;
@ -51,7 +51,7 @@ namespace E2ETest
var content = File.ReadAllText(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = File.ReadAllText($"testassets/generate/{projectName}.yaml");
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
await DockerAssert.AssertImageExistsAsync(output, "test/test-project");
}
finally
@ -90,7 +90,7 @@ namespace E2ETest
var content = File.ReadAllText(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = File.ReadAllText($"testassets/generate/{projectName}.yaml");
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
await DockerAssert.AssertImageExistsAsync(output, "test/backend");
await DockerAssert.AssertImageExistsAsync(output, "test/frontend");
@ -133,7 +133,7 @@ namespace E2ETest
var content = File.ReadAllText(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = File.ReadAllText($"testassets/generate/{projectName}.yaml");
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
await DockerAssert.AssertImageExistsAsync(output, "test/backend");
await DockerAssert.AssertImageExistsAsync(output, "test/frontend");
@ -173,7 +173,7 @@ namespace E2ETest
var content = File.ReadAllText(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = File.ReadAllText($"testassets/generate/{projectName}-noregistry.yaml");
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
await DockerAssert.AssertImageExistsAsync(output, "test-project");
}

7
test/E2ETest/TyeInitTests.cs

@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using Microsoft.Tye;
using Xunit;
@ -36,7 +37,7 @@ namespace E2ETest
output.WriteLine(content);
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
}
[Fact]
@ -56,7 +57,7 @@ namespace E2ETest
output.WriteLine(content);
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
}
[Fact]
@ -76,7 +77,7 @@ namespace E2ETest
output.WriteLine(content);
Assert.Equal(expectedContent, content);
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
}
}
}

Loading…
Cancel
Save