public void CreateInitialResourceList(JObject resource) { // Create initial list of all resource without linking var type = resource.GetValueCaseInsensitive <string>("type"); var name = resource.GetValueCaseInsensitive <string>("name"); var featureSet = listOfAllPrimaryResource?.FirstOrDefault(x => x.supportedResourceTypes.Any(y => y.Equals(type, StringComparison.OrdinalIgnoreCase))); // Console.WriteLine(featureSet); if (featureSet != null) { ResourceNode resourceNode = new ResourceNode(); resourceNode.Token = "Token" + index++; ResourceModel resourceModel = new ResourceModel(); resourceModel.FeatureName = featureSet.FeatureName; resourceModel.ResourceType = type; resourceModel.ResourceName = name; resourceModel.Resource = resource; resourceNode.Resource = resourceModel; resourceNode.count = 1; ResourceList.Add(resourceNode); } }
public IList <ControlResult> Evaluate(JObject armTemplate, JObject armTemplateExternalParameters, TemplateFunctionConfig templateFunctionConfig) { var resourceEvaluator = new ResourceEvaluator(armTemplate, armTemplateExternalParameters); var results = new List <ControlResult>(); // Get list of all primary resources var listOfAllPrimaryResource = _resourceControlSets.Select(x => new { SupportedResourceTypes = x.supportedResourceTypes, FeatureName = x.FeatureName }).ToList();//.ToDictionary(x=>x.ResourceType,x=>x.FeatureName); // Fetch all resources , variables , parameters var resources = armTemplate.GetValueCaseInsensitive("resources"); var parameters = armTemplate.GetValueCaseInsensitive("parameters"); var variables = armTemplate.GetValueCaseInsensitive("variables"); // Create a hashtable for all parameters and variables Hashtable ParamAndVarKeys = new Hashtable(); if (parameters != null) { foreach (var parameter in parameters) { var paramKey = parameter.Path.ToString().ToLower(); var paramValue = parameter.First().ToString().ToLower(); ParamAndVarKeys.Add(paramKey, paramValue); } } if (variables != null) { foreach (var variable in variables) { var variableKey = variable.Path.ToString().ToLower(); var variableValue = variable.First().ToString().ToLower(); ParamAndVarKeys.Add(variableKey, variableValue); } } List <ResourceNode> ResourceList = new List <ResourceNode>(); int index = 0; // Create initial list of all resource without linking foreach (JObject resource in resources) { var type = resource.GetValueCaseInsensitive <string>("type"); var name = resource.GetValueCaseInsensitive <string>("name"); var featureSet = listOfAllPrimaryResource?.FirstOrDefault(x => x.SupportedResourceTypes.Any(y => y.Equals(type, StringComparison.OrdinalIgnoreCase))); if (featureSet != null) { ResourceNode resourceNode = new ResourceNode(); resourceNode.Token = "Token" + index++; ResourceModel resourceModel = new ResourceModel(); resourceModel.FeatureName = featureSet.FeatureName; resourceModel.ResourceType = type; resourceModel.ResourceName = name; resourceModel.Resource = resource; resourceNode.Resource = resourceModel; ResourceList.Add(resourceNode); } } var groupedResources = ResourceList?.GroupBy(x => x.Resource.FeatureName); foreach (var featureGroup in groupedResources) { // Use for intial relation tuples List <ResourceNode> relatedResources = new List <ResourceNode>(); // use for merging relation List <ResourceNode> MergedResources = new List <ResourceNode>(); // list of resources w/o dependency List <ResourceNode> isolatedResources = new List <ResourceNode>(); foreach (var resourceNode in featureGroup.ToList()) { var resource = resourceNode.Resource; string name = resource.ResourceName; string type = resource.ResourceType; var dependsOnList = resource.Resource.GetValueCaseInsensitive("dependsOn"); bool isAnyMatchedResourceFound = false; if (dependsOnList != null && dependsOnList.Any()) { foreach (var dependency in dependsOnList) { try { string dependencyAsString = dependency.ToString().ToLower(); dependencyAsString = ParseArmFunctionAndParam(dependencyAsString, ParamAndVarKeys); var dependencyComponentArray = dependencyAsString.Split('/'); var resourceType = dependencyComponentArray[0]; var matchedResourceList = featureGroup.ToList().Where(x => x.Resource.ResourceType.StartsWith(resourceType, StringComparison.OrdinalIgnoreCase)).ToList(); foreach (var matchedResource in matchedResourceList) { var resourceNameString = ParseArmFunctionAndParam(matchedResource.Resource.ResourceName, ParamAndVarKeys); var resourceNameComponent = resourceNameString.Split('/'); if (resourceNameComponent.Last().Equals(dependencyComponentArray.Last(), StringComparison.OrdinalIgnoreCase)) { ResourceNode resourceTuple = (ResourceNode)resourceNode.Clone(); resourceTuple.LastChildResource = matchedResource; resourceTuple.ChildResource = matchedResource; relatedResources.Add(resourceTuple); MergedResources.Add(resourceTuple); isAnyMatchedResourceFound = true; } } } catch (Exception) { // No need to break execution // IF any exception occures, treat as independent resource } } } if (!isAnyMatchedResourceFound) { ResourceNode resourceTuple = (ResourceNode)resourceNode.Clone(); resourceTuple.LastChildResource = null; resourceTuple.ChildResource = null; MergedResources.Add(resourceTuple); relatedResources.Add(resourceTuple); } } List <ResourceNode> ToBeRemoved = new List <ResourceNode>(); bool isChangeHappened = false; do { isChangeHappened = false; for (int i = 0; i < MergedResources.Count; i++) { for (int j = 0; j < relatedResources.Count; j++) { if (MergedResources[i].LastChildResource != null && MergedResources[i].LastChildResource.Token.Equals(relatedResources[j].Token)) { MergedResources[i].LastChildResource.ChildResource = relatedResources[j].ChildResource; MergedResources[i].LastChildResource = relatedResources[j].LastChildResource; ToBeRemoved.Add(relatedResources[j]); isChangeHappened = true; } } } foreach (var item in ToBeRemoved) { MergedResources.Remove(item); } } while (isChangeHappened); for (int i = 0; i < MergedResources.Count; i++) { List <ResourceModel> currentResourceSet = new List <ResourceModel>(); var resourceset = (ResourceNode)MergedResources[i].Clone(); while (resourceset != null) { currentResourceSet.Add(resourceset.Resource); isolatedResources.RemoveAll(x => x.Token.Equals(resourceset.Token)); resourceset = resourceset.ChildResource; } if (currentResourceSet.Count > 0) { var resourceResults = resourceEvaluator.Evaluate(_resourceControlSets, currentResourceSet); results.AddRange(resourceResults); } } } return(results); }