private void LoadPatch( IIncludeContext includeContext, string path, List <PolicyPatch> policySet, JObject patch) { PolicyPatch p = patch.ToObject <PolicyPatch>(); p.ConditionDelegates = _conditionDelegates; string patchPath = path; p.PatchSourcePath = Path.GetRelativePath(includeContext.IncludeRoot, path) + "=>" + patch.Path; // ref patches will be added in a nested call in the else statement if (p.IncludeFile != null) { string includePath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(patchPath), p.IncludeFile)); LoadPatchFile(includeContext, includePath, File.ReadAllText(includePath), policySet); } else { policySet.Add(p); } }
private void LoadPatchFile( IIncludeContext includeContext, string path, string json, List <PolicyPatch> policySet) { JToken token = JToken.Parse(json); if (token is JArray patchArray) { patchArray .Children <JObject>() .ToList() .ForEach(patch => { LoadPatch(includeContext, path, policySet, patch); }); return; } if (token is JObject patchObj) { LoadPatch(includeContext, path, policySet, patchObj); } }
public bool Build(IIncludeContext includeContext) { CleanPreviousOutput(includeContext); _logMessageSink.Message($"{nameof(includeContext.OutputRoot)}:{Path.GetFullPath(includeContext.OutputRoot)}"); _logMessageSink.Message($"{nameof(includeContext.ConfigRoot)}:{Path.GetFullPath(includeContext.ConfigRoot)}"); _logMessageSink.Message($"{nameof(includeContext.IncludeRoot)}:{Path.GetFullPath(includeContext.IncludeRoot)}"); _logMessageSink.Message($"Resolved include paths: \n{string.Join("\n", includeContext.ResolvedIncludeRoots)}"); Stopwatch sw = new Stopwatch(); _logMessageSink.Message("Beginning generation process..."); sw.Start(); List <Task> tasks = new List <Task>(); // The TransformationContext has caching capabilities that are based on a concurrent dictionary. // Create it here to share things like resolved files while applying transformations to different output files ConcurrentDictionary <string, object> objectCache = new ConcurrentDictionary <string, object>(); foreach (string role in _environmentDescription.Roles) { foreach (StageDefinition stage in _environmentDescription.Stages) { foreach (ServerDefinition server in stage.Servers) { if (!server.Roles.Contains(role)) { continue; } if (!Directory.Exists(server.OutputPath)) { Directory.CreateDirectory(server.OutputPath); } if (_initConfig.Debug) { PerformTransformations(objectCache, includeContext, server, role, stage); continue; } tasks.Add(Task.Run(() => { PerformTransformations(objectCache, includeContext, server, role, stage); })); } } } if (!_initConfig.Debug) { Task.WaitAll(tasks.ToArray()); } sw.Stop(); return(DetermineResult(sw)); }
private static void CleanPreviousOutput(IIncludeContext includeContext) { if (Directory.Exists(includeContext.OutputRoot)) { Directory.Delete(includeContext.OutputRoot, true); Directory.CreateDirectory(includeContext.OutputRoot); } }
private void PerformTransformations( ConcurrentDictionary <string, object> objectCache, IIncludeContext includeContext, ServerDefinition server, string role, StageDefinition stage) { _logMessageSink.EnterBlock(sink => { string environmentPath = Path.Combine(server.OutputPath, $"{role}.json"); try { sink.Message($"------------------------------------------------------------------------------------------------------\nStarting {environmentPath}"); TargetingInformation targetingInformation = new TargetingInformation { Replication = server.Replication, Role = role, Stage = stage.Stage, Server = server.Server }; // This needs to be created per file creation thread TransformationContext transformationContext = new TransformationContext(); // use the shared cache created in the wrapping service method to share resource reads. transformationContext.Cache = objectCache; PatchingTemplate template = _templateProvider.GetTemplate(transformationContext, targetingInformation.Role); JArray runtimeTemplate = JArray.Parse(template.String); transformationContext.SetPluginPolicy(includeContext); transformationContext.SetPluginPolicy(targetingInformation); transformationContext.SetPluginPolicy(sink); _transformationEngine.EvaluateMakros(transformationContext, runtimeTemplate); File.WriteAllText(environmentPath, JsonConvert.SerializeObject(runtimeTemplate, Formatting.Indented)); sink.Message($"Finished {environmentPath}\n------------------------------------------------------------------------------------------------------"); } catch (Exception e) { sink.Error($"Error while generating {environmentPath}...\n{e.ToString()}"); } }); }
public IEnumerable <IPolicyPatch> GetTargetedPatches( ITransformationContext transformationContext, IIncludeContext includeContext, string patchExtension) { return(CollectFromIncludeLocations( transformationContext, includeContext, patchExtension) // patch applies by targeting information .Where(p => p.CanApply(transformationContext)) // and has additional conditions (match property) // this indicates that this is not a base patch .Where(p => p.Match?.Properties().Any() ?? false)); }
public IEnumerable <IPolicyPatch> GetBasePatches( ITransformationContext transformationContext, IIncludeContext includeContext, string patchExtension) { return(CollectFromIncludeLocations( transformationContext, includeContext, patchExtension) .Where(p => p.CanApply(transformationContext)) .Where(p => !p.Match?.Properties() .Any() ?? false) .ToArray()); }
public bool TryHandle(ITransformationContext transformationContext, JToken makro, string[] makroArguments) { if (makroArguments.Length != 2 || makroArguments[0] != "PATCH") { return(false); } JArray array = (JArray)makro.Parent; int index = array.IndexOf(makro); array.RemoveAt(index); string extensionToken = makroArguments[1]; IIncludeContext includeContext = transformationContext.GetPluginPolicy <IIncludeContext>(); ILogMessageSink logger = transformationContext.GetPluginPolicy <ILogMessageSink>(); IEnumerable <(IPolicyPatch, IEnumerable <JObject>)> basePatches = _patchCollector .GetBasePatches(transformationContext, includeContext, $"{extensionToken}.json") .Select(p => (p, p.GetPolicies())); foreach ((IPolicyPatch, IEnumerable <JObject>)patch in basePatches) { foreach (JObject policy in patch.Item2) { string sourceTerm = CreateSourceTerm(policy, patch.Item1.PatchSourcePath, "Base"); AppendPatchSource(policy, sourceTerm); logger.Message(sourceTerm); array.Insert(index, policy); index++; } } IEnumerable <IPolicyPatch> targetedPatches = _patchCollector .GetTargetedPatches(transformationContext, includeContext, $"{extensionToken}.json"); foreach (IPolicyPatch policy in targetedPatches) { ApplyPatch(logger, policy, array); } return(true); }
private ImmutableSortedDictionary <string, string> GetPatchCache( ITransformationContext transformationContext, IIncludeContext includeContext, string patchToken) { return(transformationContext .GetOrAddCacheEntry( includeContext.IncludeRoot + "|" + patchToken, () => includeContext .ResolvedIncludeRoots .SelectMany(r => Directory.GetFiles(r, $"*{patchToken}", SearchOption.AllDirectories)) .Distinct() .Select(path => (path, File.ReadAllText(path))) .OrderBy(p => Path.GetRelativePath(includeContext.IncludeRoot, p.Item1)) .ToImmutableSortedDictionary(k => k.Item1, v => v.Item2))); }
private IEnumerable <IPolicyPatch> CollectFromIncludeLocations( ITransformationContext transformationContext, IIncludeContext includeContext, string patchToken) { List <PolicyPatch> policySet = new List <PolicyPatch>(); ImmutableSortedDictionary <string, string> patches = GetPatchCache(transformationContext, includeContext, patchToken); foreach (KeyValuePair <string, string> file in patches) { LoadPatchFile(includeContext, file.Key, file.Value, policySet); } return(policySet); }