From cb00b7cc2f15c587beaf514ca9316df96916691d Mon Sep 17 00:00:00 2001 From: Yue Fei <59813791+moria97@users.noreply.github.com> Date: Tue, 8 Dec 2020 14:26:40 +0800 Subject: [PATCH] Use default templates as embedded resource (#119) * Change nuget spec * Update template management project and unit tests * Change VS Macros to relative path. * Fix pre-build command format * Change slash in command. * Remove debug info * Recover load default templates from file api Co-authored-by: Yue Fei --- .../TemplateCollectionProviderTests.cs | 3 +- .../TemplateCollectionProviderFactory.cs | 12 +++++- ...rosoft.Health.Fhir.Liquid.Converter.nuspec | 2 +- ...soft.Health.Fhir.TemplateManagement.csproj | 10 +++++ .../Models/TemplateLayer.cs | 38 +++++++++++++++++-- .../Utilities/StreamUtility.cs | 11 ++++++ 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Health.Fhir.TemplateManagement.UnitTests/Providers/TemplateCollectionProviderTests.cs b/src/Microsoft.Health.Fhir.TemplateManagement.UnitTests/Providers/TemplateCollectionProviderTests.cs index ca759dc35..e243daaf6 100644 --- a/src/Microsoft.Health.Fhir.TemplateManagement.UnitTests/Providers/TemplateCollectionProviderTests.cs +++ b/src/Microsoft.Health.Fhir.TemplateManagement.UnitTests/Providers/TemplateCollectionProviderTests.cs @@ -29,8 +29,7 @@ public class TemplateCollectionProviderTests : ArtifactProviderTests public TemplateCollectionProviderTests() { - var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DefaultTemplates.tar.gz"); - TemplateLayer defaultTempalteLayer = TemplateLayer.ReadFromFile(path); + TemplateLayer defaultTempalteLayer = TemplateLayer.ReadFromEmbeddedResource(); _cache.Set(ImageInfo.DefaultTemplateImageReference, defaultTempalteLayer, new MemoryCacheEntryOptions() { AbsoluteExpiration = System.Runtime.Caching.ObjectCache.InfiniteAbsoluteExpiration, Size = 0 }); PushLargeSizeManifest(); diff --git a/src/Microsoft.Health.Fhir.TemplateManagement/Factory/TemplateCollectionProviderFactory.cs b/src/Microsoft.Health.Fhir.TemplateManagement/Factory/TemplateCollectionProviderFactory.cs index 38556fbb1..81c41a8f0 100644 --- a/src/Microsoft.Health.Fhir.TemplateManagement/Factory/TemplateCollectionProviderFactory.cs +++ b/src/Microsoft.Health.Fhir.TemplateManagement/Factory/TemplateCollectionProviderFactory.cs @@ -59,12 +59,20 @@ public ITemplateCollectionProvider CreateTemplateCollectionProvider(string image return new TemplateCollectionProvider(imageInfo, client, _templateCache, _configuration); } - public void InitDefaultTemplates(string path = null) + public void InitDefaultTemplates() + { + TemplateLayer defaultTemplateLayer = TemplateLayer.ReadFromEmbeddedResource(); + _templateCache.Set(ImageInfo.DefaultTemplateImageReference, defaultTemplateLayer, new MemoryCacheEntryOptions() { AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration, Size = defaultTemplateLayer.Size, Priority = Extensions.Caching.Memory.CacheItemPriority.NeverRemove }); + _templateCache.Set(defaultTemplateLayer.Digest, defaultTemplateLayer, new MemoryCacheEntryOptions() { AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration, Size = defaultTemplateLayer.Size, Priority = Extensions.Caching.Memory.CacheItemPriority.NeverRemove }); + } + + public void InitDefaultTemplates(string path) { path ??= Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constants.DefaultTemplatePath); + TemplateLayer defaultTemplateLayer = TemplateLayer.ReadFromFile(path); _templateCache.Set(ImageInfo.DefaultTemplateImageReference, defaultTemplateLayer, new MemoryCacheEntryOptions() { AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration, Size = defaultTemplateLayer.Size, Priority = Extensions.Caching.Memory.CacheItemPriority.NeverRemove }); - _templateCache.Set(StreamUtility.CalculateDigestFromSha256(File.ReadAllBytes(path)), defaultTemplateLayer, new MemoryCacheEntryOptions() { AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration, Size = defaultTemplateLayer.Size, Priority = Extensions.Caching.Memory.CacheItemPriority.NeverRemove }); + _templateCache.Set(defaultTemplateLayer.Digest, defaultTemplateLayer, new MemoryCacheEntryOptions() { AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration, Size = defaultTemplateLayer.Size, Priority = Extensions.Caching.Memory.CacheItemPriority.NeverRemove }); } } } diff --git a/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.Liquid.Converter.nuspec b/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.Liquid.Converter.nuspec index 2581071f8..65d2f929c 100644 --- a/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.Liquid.Converter.nuspec +++ b/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.Liquid.Converter.nuspec @@ -27,7 +27,7 @@ - + diff --git a/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.TemplateManagement.csproj b/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.TemplateManagement.csproj index bf135d71b..d5cce43a1 100644 --- a/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.TemplateManagement.csproj +++ b/src/Microsoft.Health.Fhir.TemplateManagement/Microsoft.Health.Fhir.TemplateManagement.csproj @@ -30,5 +30,15 @@ + + + + DefaultTemplates.tar.gz + + + + + + \ No newline at end of file diff --git a/src/Microsoft.Health.Fhir.TemplateManagement/Models/TemplateLayer.cs b/src/Microsoft.Health.Fhir.TemplateManagement/Models/TemplateLayer.cs index a592ebba5..2fb2d174b 100644 --- a/src/Microsoft.Health.Fhir.TemplateManagement/Models/TemplateLayer.cs +++ b/src/Microsoft.Health.Fhir.TemplateManagement/Models/TemplateLayer.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using DotLiquid; using Microsoft.Health.Fhir.TemplateManagement.Exceptions; using Microsoft.Health.Fhir.TemplateManagement.Utilities; @@ -17,21 +18,50 @@ public class TemplateLayer : OCIArtifactLayer { public Dictionary TemplateContent { get; set; } + public static TemplateLayer ReadFromEmbeddedResource() + { + try + { + var defaultTemplateResourceName = $"{typeof(Constants).Namespace}.{Constants.DefaultTemplatePath}"; + using Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(defaultTemplateResourceName); + return ReadFromStream(resourceStream); + } + catch (Exception ex) + { + throw new DefaultTemplatesInitializeException(TemplateManagementErrorCode.InitializeDefaultTemplateFailed, $"Load default template failed.", ex); + } + } + public static TemplateLayer ReadFromFile(string filePath) { try { + using Stream fielStream = File.OpenRead(filePath); + return ReadFromStream(fielStream); + } + catch (Exception ex) + { + throw new DefaultTemplatesInitializeException(TemplateManagementErrorCode.InitializeDefaultTemplateFailed, $"Load default template failed.", ex); + } + } + + private static TemplateLayer ReadFromStream(Stream stream) + { + try + { + var digest = StreamUtility.CalculateDigestFromSha256(stream); + stream.Position = 0; + TemplateLayer templateLayer = new TemplateLayer(); - var rawBytes = File.ReadAllBytes(filePath); - var artifacts = StreamUtility.DecompressTarGzStream(new MemoryStream(rawBytes)); + var artifacts = StreamUtility.DecompressTarGzStream(stream); templateLayer.TemplateContent = TemplateLayerParser.ParseToTemplates(artifacts); - templateLayer.Digest = StreamUtility.CalculateDigestFromSha256(File.ReadAllBytes(filePath)); + templateLayer.Digest = digest; templateLayer.Size = artifacts.Sum(x => x.Value.Length); return templateLayer; } catch (Exception ex) { - throw new DefaultTemplatesInitializeException(TemplateManagementErrorCode.InitializeDefaultTemplateFailed, $"Load default template from {filePath} failed", ex); + throw new DefaultTemplatesInitializeException(TemplateManagementErrorCode.InitializeDefaultTemplateFailed, $"Load default template failed.", ex); } } } diff --git a/src/Microsoft.Health.Fhir.TemplateManagement/Utilities/StreamUtility.cs b/src/Microsoft.Health.Fhir.TemplateManagement/Utilities/StreamUtility.cs index f2786c093..f92904605 100644 --- a/src/Microsoft.Health.Fhir.TemplateManagement/Utilities/StreamUtility.cs +++ b/src/Microsoft.Health.Fhir.TemplateManagement/Utilities/StreamUtility.cs @@ -74,5 +74,16 @@ public static string CalculateDigestFromSha256(byte[] content) hashedValue += string.Join(string.Empty, hashedStrings); return hashedValue; } + + public static string CalculateDigestFromSha256(Stream stream) + { + using SHA256 mySHA256 = SHA256.Create(); + string hashedValue = "sha256:"; + byte[] hashData = mySHA256.ComputeHash(stream); + string[] hashedStrings = hashData.Select(x => string.Format("{0,2:x2}", x)).ToArray(); + hashedValue += string.Join(string.Empty, hashedStrings); + return hashedValue; + } + } }