TemplatesGenerator.cs
using System;
using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using APIManagementTemplate.Models; using Newtonsoft.Json.Linq; namespace APIManagementTemplate { public class GeneratedTemplate { public string FileName { get; set; } public string Directory { get; set; } public JObject Content { get; set; } public string XmlContent { get; set; } public ContentType Type { get; set; } = ContentType.Json; public List<string> ExternalDependencies = new List<string>(); public string GetPath() { return Directory == String.Empty ? $"/{FileName}" : $"/{Directory}/{FileName}"; } public string GetUnixPath() { return GetPath().Replace(@"\", "/"); } public string GetShortPath() { return FileName; } } public class FileInfo { public FileInfo(string fileName, string directory) { FileName = fileName; Directory = directory; } public string FileName { get; set; } public string Directory { get; set; } } public enum ContentType { Json, Xml } public class TemplatesGenerator { private const string ProductResourceType = "Microsoft.ApiManagement/service/products"; private const string ApiResourceType = "Microsoft.ApiManagement/service/apis"; private const string ServiceResourceType = "Microsoft.ApiManagement/service"; private const string ServicePolicyResourceType = "Microsoft.ApiManagement/service/policies"; private const string StorageAccountResourceType = "Microsoft.Storage/storageAccounts"; private const string SubscriptionResourceType = "Microsoft.ApiManagement/service/subscriptions"; private const string UserResourceType = "Microsoft.ApiManagement/service/users"; private const string GroupResourceType = "Microsoft.ApiManagement/service/groups"; private const string UserGroupResourceType = "Microsoft.ApiManagement/service/groups/users"; private const string OperationalInsightsWorkspaceResourceType = "Microsoft.OperationalInsights/workspaces"; private const string AppInsightsResourceType = "Microsoft.Insights/components"; private const string ProductPolicyResourceType = "Microsoft.ApiManagement/service/products/policies"; private const string ApiOperationResourceType = "Microsoft.ApiManagement/service/apis/operations"; private const string ApiOperationPolicyResourceType = "Microsoft.ApiManagement/service/apis/operations/policies"; private const string ApiPolicyResourceType = "Microsoft.ApiManagement/service/apis/policies"; private const string ServicePolicyFileName = "service.policy.xml"; private const string PropertyResourceType = "Microsoft.ApiManagement/service/properties"; private const string BackendResourceType = "Microsoft.ApiManagement/service/backends"; private const string OpenIdConnectProviderResourceType = "Microsoft.ApiManagement/service/openidConnectProviders"; private const string CertificateResourceType = "Microsoft.ApiManagement/service/certificates"; public const string TemplatesStorageAccountSASToken = "_artifactsLocationSasToken"; private const string MasterTemplateJson = "master.template.json"; private const string ProductAPIResourceType = "Microsoft.ApiManagement/service/products/apis"; public IList<GeneratedTemplate> Generate(string sourceTemplate, bool apiStandalone, bool separatePolicyFile = false, bool generateParameterFiles = false, bool replaceListSecretsWithParameter = false) { JObject parsedTemplate = JObject.Parse(sourceTemplate); if (replaceListSecretsWithParameter) ReplaceListSecretsWithParameter(parsedTemplate); List <GeneratedTemplate> templates = GenerateAPIsAndVersionSets(apiStandalone, parsedTemplate, separatePolicyFile); templates.AddRange(GenerateProducts(parsedTemplate, separatePolicyFile, apiStandalone)); templates.AddRange(GenerateService(parsedTemplate, separatePolicyFile)); templates.Add(GenerateTemplate(parsedTemplate, "subscriptions.template.json", String.Empty, SubscriptionResourceType)); templates.Add(GenerateTemplate(parsedTemplate, "users.template.json", String.Empty, UserResourceType)); templates.Add(GenerateTemplate(parsedTemplate, "groups.template.json", String.Empty, GroupResourceType)); templates.Add(GenerateTemplate(parsedTemplate, "groupsUsers.template.json", String.Empty, UserGroupResourceType)); MoveExternalDependencies(templates); templates.Add(GenerateMasterTemplate(templates.Where(x => x.Type == ContentType.Json).ToList(), parsedTemplate, separatePolicyFile, apiStandalone)); templates.AddRange(GenerateAPIMasterTemplate(templates, parsedTemplate, separatePolicyFile, apiStandalone)); MoveExternalDependencies(templates.Where(x => x.FileName.StartsWith("api-") && x.FileName.EndsWith(MasterTemplateJson)).ToList()); if (generateParameterFiles) { templates.Add(GenerateParameterFile(templates.FirstOrDefault(x => x.FileName == MasterTemplateJson && x.Directory == String.Empty))); foreach (GeneratedTemplate template in templates.Where(x => x.FileName.EndsWith(".master.template.json")).ToArray()) { templates.Add(GenerateParameterFile(template, true)); } } return templates; } private void ReplaceListSecretsWithParameter(JObject parsedTemplate) { var properties = parsedTemplate.SelectTokens("$.resources[?(@.type=='Microsoft.ApiManagement/service/properties')]").Where(x => x["properties"]?.Value<string>("value").StartsWith("[listsecrets(") ?? false); foreach (JToken property in properties) { var displayName = property["properties"].Value<string>("displayName"); property["properties"]["value"] = $"[parameters('{displayName}')]"; parsedTemplate["parameters"][displayName]= JToken.FromObject(new { type = "securestring", defaultValue = String.Empty }); } } private void MoveExternalDependencies(List<GeneratedTemplate> templates) { foreach (GeneratedTemplate template in templates.Where(x => x.Type == ContentType.Json)) { var dependsOn = template.Content.SelectTokens("$..dependsOn[*]").ToList(); foreach (JToken dependency in dependsOn) { var name = dependency.Value<string>(); if (!IsLocalDependency(name, template)) { template.ExternalDependencies.Add(name); dependency.Remove(); } } } } private static bool IsLocalDependency(string name, GeneratedTemplate template) { var resourceType = GetSplitPart(1, name); var nameParts = name.Split(',').Skip(1).Select(x => x.Trim().Replace("'))]", "')").Replace("')]", "')")); var localDependency = template.Content.SelectTokens($"$..resources[?(@.type=='{resourceType}')]") .Any(resource => nameParts.All(namePart => NameContainsPart(resource, namePart))); return localDependency; } private static bool NameContainsPart(JToken resource, string namePart) { string name = resource.Value<string>("name").ToLowerInvariant(); string part = namePart.ToLowerInvariant(); return name.Contains(part) || (part.StartsWith("'") && name.Contains($"'/{part.Split('\'')[1]}'")); } private IEnumerable<GeneratedTemplate> GenerateAPIMasterTemplate(List<GeneratedTemplate> templates, JObject parsedTemplate, bool separatePolicyFile, bool apiStandalone) { var masterApis = new List<GeneratedTemplate>(); foreach (var versionSet in templates.Where(x => x.FileName.EndsWith(".version-set.template.json"))) { masterApis.Add(GeneratedMasterTemplate2(parsedTemplate, separatePolicyFile, $"{versionSet.Directory}.master.template.json", versionSet.Directory, templates.Where(x => x.Directory.StartsWith(versionSet.Directory) && x.Type == ContentType.Json), templates.Where(x => x.Type == ContentType.Json).ToList())); } return masterApis; } private GeneratedTemplate GenerateParameterFile(GeneratedTemplate masterTemplate, bool apiMasterParameterFile = false) { var generatedTemplate = new GeneratedTemplate { Directory = masterTemplate.Directory, FileName = masterTemplate.FileName.Replace(".template.json", ".parameters.json") }; DeploymentParameters template = new DeploymentParameters(); var parameters = masterTemplate.Content["parameters"]; var excludedParameters = new List<string> {TemplatesStorageAccountSASToken}; if (apiMasterParameterFile) { excludedParameters.Add("repoBaseUrl"); excludedParameters.Add("apimServiceName"); } foreach (JProperty parameter in parameters.Cast<JProperty>().Where(p => excludedParameters.All(e => e != p.Name))) { string name = parameter.Name; string type = parameter.Value["type"].Value<string>(); switch (type) { case "bool": bool boolValue = parameter.Value["defaultValue"]?.Value<bool>() ?? false; template.AddParameter(name, boolValue); break; default: string value = parameter.Value["defaultValue"]?.Value<string>() ?? String.Empty; template.AddParameter(name, value); break; } } generatedTemplate.Content = JObject.FromObject(template); return generatedTemplate; } private GeneratedTemplate GenerateMasterTemplate(List<GeneratedTemplate> generatedTemplates, JObject parsedTemplate, bool separatePolicyFile, bool apiStandalone) { return GeneratedMasterTemplate2(parsedTemplate, separatePolicyFile, MasterTemplateJson, String.Empty, generatedTemplates.Where(x => !apiStandalone || !x.Directory.StartsWith("api-")), generatedTemplates); } private GeneratedTemplate GeneratedMasterTemplate2(JObject parsedTemplate, bool separatePolicyFile, string fileName, string directory, IEnumerable<GeneratedTemplate> filteredTemplates, List<GeneratedTemplate> generatedTemplates) { var generatedTemplate = new GeneratedTemplate {Directory = directory, FileName = fileName}; DeploymentTemplate template = new DeploymentTemplate(true, true); foreach (GeneratedTemplate template2 in filteredTemplates) { template.resources.Add(GenerateDeployment(template2, generatedTemplates)); } template.parameters = GetParameters(parsedTemplate["parameters"], template.resources, separatePolicyFile); generatedTemplate.Content = JObject.FromObject(template); return generatedTemplate; } private JObject GetParameters(JToken parameters, IList<JObject> resources, bool separatePolicyFile) { var p = resources.Select(x => GetParameters(parameters, x)).ToArray(); var allParameters = p[0]; foreach (JObject jObject in p.Skip(1)) { allParameters.Merge(jObject); } if (!separatePolicyFile) { if (allParameters["repoBaseUrl"] == null) { allParameters["repoBaseUrl"] = JToken.FromObject(new { type = "string", metadata = new {description = "Base URL of the repository"} }); } if (allParameters[TemplatesStorageAccountSASToken] == null) { allParameters[TemplatesStorageAccountSASToken] = JToken.FromObject(new { type = "securestring", defaultValue = String.Empty }); } } return allParameters; } private JObject GenerateDeployment(GeneratedTemplate template2, List<GeneratedTemplate> generatedTemplates) { var deployment = new { apiVersion = "2017-05-10", name = template2.GetShortPath(), type ="Microsoft.Resources/deployments", properties = new { mode = "Incremental", templateLink = new { uri = $"[concat(parameters('repoBaseUrl'), '{template2.GetUnixPath()}', parameters('{TemplatesStorageAccountSASToken}'))]", contentVersion = "1.0.0.0" }, parameters = GenerateDeploymentParameters(template2) }, dependsOn = GenerateDeploymentDependsOn(template2, generatedTemplates) }; return JObject.FromObject(deployment); } private JArray GenerateDeploymentDependsOn(GeneratedTemplate template, List<GeneratedTemplate> generatedTemplates) { var dependsOn = new JArray(); foreach (string name in template.ExternalDependencies) { var matches = generatedTemplates.Where(t => IsLocalDependency(name, t)); if(matches.Any()) { var match = matches.First(); dependsOn.Add($"[resourceId('Microsoft.Resources/deployments', '{match.GetShortPath()}')]"); } else { var notFound = true; } } return dependsOn; } private JObject GenerateDeploymentParameters(GeneratedTemplate template2) { var parameters = new JObject(); var parametersFromTemplate = template2.Content["parameters"]; foreach (JProperty token in parametersFromTemplate.Cast<JProperty>()) { var name = token.Name; parameters.Add(name, JObject.FromObject(new {value = $"[parameters('{name}')]"})); } return parameters; } private IEnumerable<GeneratedTemplate> GenerateService(JObject parsedTemplate, bool separatePolicyFile) { List<GeneratedTemplate> templates = new List<GeneratedTemplate>(); string[] wantedResources = { ServiceResourceType,OperationalInsightsWorkspaceResourceType, AppInsightsResourceType, StorageAccountResourceType }; var generatedTemplate = new GeneratedTemplate { FileName = "service.template.json", Directory = String.Empty }; DeploymentTemplate template = new DeploymentTemplate(true, true); var resources = parsedTemplate.SelectTokens("$.resources[*]") .Where(r => wantedResources.Any(w => w == r.Value<string>("type"))); foreach (JToken resource in resources) { if (resource.Value<string>("type") == ServiceResourceType) { AddServiceResources(parsedTemplate, resource, PropertyResourceType); AddServiceResources(parsedTemplate, resource, BackendResourceType); AddServiceResources(parsedTemplate, resource, OpenIdConnectProviderResourceType); AddServiceResources(parsedTemplate, resource, CertificateResourceType); if (separatePolicyFile) { var policy = resource.SelectToken($"$..resources[?(@.type==\'{ServicePolicyResourceType}\')]"); if (policy != null) { templates.Add(GenerateServicePolicyFile(parsedTemplate, policy)); ReplacePolicyWithFileLink(policy, new FileInfo(ServicePolicyFileName, String.Empty)); } } } template.parameters = GetParameters(parsedTemplate["parameters"], resource); template.resources.Add(JObject.FromObject(resource)); } generatedTemplate.Content = JObject.FromObject(template); templates.Add(generatedTemplate); return templates; } private static void AddServiceResources(JObject parsedTemplate, JToken resource, string resourceType) { var properties = parsedTemplate.SelectTokens($"$..resources[?(@.type==\'{resourceType}\')]"); JArray subResources = (JArray) resource["resources"]; foreach (JToken property in properties.ToArray()) { subResources.Add(property); } } private List<GeneratedTemplate> GenerateAPIsAndVersionSets(bool apiStandalone, JObject parsedTemplate, bool separatePolicyFile) { var apis = parsedTemplate["resources"].Where(rr => rr["type"].Value<string>() == ApiResourceType); List<GeneratedTemplate> templates = separatePolicyFile? GenerateAPIPolicyFiles(apis, parsedTemplate).ToList() : new List<GeneratedTemplate>(); templates.AddRange(apis.Select(api => GenerateAPI(api, parsedTemplate, apiStandalone, separatePolicyFile))); var versionSets = apis.Where(api => api["properties"]["apiVersionSetId"] != null) .Distinct(new ApiVersionSetIdComparer()) .Select(api => GenerateVersionSet(api, parsedTemplate, apiStandalone)).ToList(); templates.AddRange(versionSets); return templates; } private IEnumerable<GeneratedTemplate> GenerateAPIPolicyFiles(IEnumerable<JToken> apis, JObject parsedTemplate) { var policyFiles = new List<GeneratedTemplate>(); foreach (JToken api in apis) { var apiPolicy = api["resources"].FirstOrDefault(x => x.Value<string>("type") == ApiPolicyResourceType); if (apiPolicy != null) { policyFiles.Add(GeneratePolicyFile(parsedTemplate, apiPolicy, api, String.Empty)); } var operations = api["resources"].Where(x => x.Value<string>("type") == ApiOperationResourceType); foreach (var operation in operations) { var policy = operation["resources"].FirstOrDefault(x => x.Value<string>("type") == ApiOperationPolicyResourceType); if (policy != null) { var operationId = GetParameterPart(operation, "name", -2); policyFiles.Add(GeneratePolicyFile(parsedTemplate, policy, api, operationId)); } } } return policyFiles; } private static GeneratedTemplate GeneratePolicyFile(JObject parsedTemplate, JToken policy, JToken api, string operationId) { var content = policy["properties"].Value<string>("policyContent"); var template = new GeneratedTemplate { Type = ContentType.Xml, XmlContent = content }; var filenameAndDirectory = GetFilenameAndDirectoryForOperationPolicy(api, parsedTemplate, operationId); template.FileName = filenameAndDirectory.FileName; template.Directory = filenameAndDirectory.Directory; return template; } private static GeneratedTemplate GenerateServicePolicyFile(JObject parsedTemplate, JToken policy) { var content = policy["properties"].Value<string>("policyContent"); var template = new GeneratedTemplate { Type = ContentType.Xml, XmlContent = content, FileName = ServicePolicyFileName, Directory = String.Empty }; return template; } private IEnumerable<GeneratedTemplate> GenerateProducts(JObject parsedTemplate, bool separatePolicyFile, bool apiStandalone) { var products = parsedTemplate["resources"].Where(rr => rr["type"].Value<string>() == ProductResourceType); List<GeneratedTemplate> templates = new List<GeneratedTemplate>(); if (separatePolicyFile) { templates.AddRange(products.Select(p => GenerateProductPolicy(p)).Where(x => x != null)); } templates.AddRange(products .Select(product => GenerateProduct(product, parsedTemplate, separatePolicyFile, apiStandalone))); return templates; } private GeneratedTemplate GenerateProductPolicy(JToken product) { var productId = GetParameterPart(product, "name", -2).Substring(1); var policy = product["resources"] .FirstOrDefault(rr => rr["type"].Value<string>() == ProductPolicyResourceType); if (policy?["properties"] == null) return null; var content = policy["properties"].Value<string>("policyContent"); return new GeneratedTemplate { Directory = $"product-{productId}", FileName = $"product-{productId}.policy.xml", Type = ContentType.Xml, XmlContent = content }; } private GeneratedTemplate GenerateProduct(JToken product, JObject parsedTemplate, bool separatePolicyFile, bool apiStandalone) { var productId = GetParameterPart(product, "name", -2).Substring(1); GeneratedTemplate generatedTemplate = new GeneratedTemplate { Directory = $"product-{productId}", FileName = $"product-{productId}.template.json" }; DeploymentTemplate template = new DeploymentTemplate(true, true); if (separatePolicyFile) { ReplaceProductPolicyWithFileLink(product, productId); AddParametersForFileLink(parsedTemplate); } template.parameters = GetParameters(parsedTemplate["parameters"], product); template.resources.Add(JObject.FromObject(product)); generatedTemplate.Content = JObject.FromObject(template); if (apiStandalone) RemoveProductAPIs(generatedTemplate.Content); return generatedTemplate; } private void RemoveProductAPIs(JObject content) { var apis = content.SelectTokens($"$..resources[?(@.type=='{ProductAPIResourceType}')]"); foreach (var api in apis.ToArray()) { api.Remove(); } } private void AddParametersForFileLink(JToken template) { var parameters = template["parameters"]; if (parameters != null) { parameters["repoBaseUrl"] = JToken.FromObject(new { type = "string", metadata = new {description = "Base URL of the repository"} }); parameters[TemplatesStorageAccountSASToken] = JToken.FromObject(new { type = "securestring", defaultValue = String.Empty }); } } private void ReplaceProductPolicyWithFileLink(JToken product, string productId) { var policy = product["resources"].FirstOrDefault(x => x.Value<string>("type") == ProductPolicyResourceType); if (policy != null) { policy["apiVersion"] = "2018-01-01"; policy["properties"]["contentFormat"] = "xml-link"; policy["properties"]["policyContent"] = $"[concat(parameters('repoBaseUrl'), '/product-{productId}/product-{productId}.policy.xml', parameters('{TemplatesStorageAccountSASToken}'))]"; } } private void ReplaceApiOperationPolictPolicyWithFileLink(JToken api, JObject parsedTemplate) { ReplacePoliciesWithFileLink(api, ApiOperationPolicyResourceType, policy => GetParameterPart(policy, "name", -6), parsedTemplate); ReplacePoliciesWithFileLink(api, ApiPolicyResourceType, policy => String.Empty, parsedTemplate); } private static void ReplacePoliciesWithFileLink(JToken api, string policyResourceType, Func<JToken, string> operationIdFunc, JObject parsedTemplate) { var jpath = $"$..resources[?(@.type==\'{policyResourceType}\')]"; var policies = api.SelectTokens(jpath); foreach (JToken policy in policies) { var operationId = operationIdFunc(policy); ReplacePolicyWithFileLink(api, parsedTemplate, operationId, policy); } } private static void ReplacePolicyWithFileLink(JToken api, JObject parsedTemplate, string operationId, JToken policy) { var fileInfo = GetFilenameAndDirectoryForOperationPolicy(api, parsedTemplate, operationId); ReplacePolicyWithFileLink(policy, fileInfo); } private static void ReplacePolicyWithFileLink(JToken policy, FileInfo fileInfo) { policy["properties"]["contentFormat"] = "xml-link"; policy["apiVersion"] = "2018-01-01"; string formattedDirectory = fileInfo.Directory.Replace(@"\", "/"); var directory = $"/{formattedDirectory}"; if (directory == "/") directory = String.Empty; policy["properties"]["policyContent"] = $"[concat(parameters('repoBaseUrl'), '{directory}/{fileInfo.FileName}', parameters('{TemplatesStorageAccountSASToken}'))]"; } private static GeneratedTemplate GenerateTemplate(JObject parsedTemplate, string filename, string directory, params string[] wantedResources) { var generatedTemplate = new GeneratedTemplate {Directory = directory, FileName = filename}; DeploymentTemplate template = new DeploymentTemplate(true, true); var resources = parsedTemplate.SelectTokens("$.resources[*]") .Where(r => wantedResources.Any(w => w == r.Value<string>("type"))); foreach (JToken resource in resources) { template.parameters = GetParameters(parsedTemplate["parameters"], resource); template.resources.Add(JObject.FromObject(resource)); } generatedTemplate.Content = JObject.FromObject(template); return generatedTemplate; } private GeneratedTemplate GenerateVersionSet(JToken api, JObject parsedTemplate, bool apiStandalone) { GeneratedTemplate generatedTemplate = new GeneratedTemplate(); DeploymentTemplate template = new DeploymentTemplate(true, true); SetFilenameAndDirectoryForVersionSet(api, generatedTemplate, parsedTemplate); var versionSetId = GetParameterPart(api["properties"], "apiVersionSetId", -2); var versionSet = parsedTemplate .SelectTokens("$.resources[?(@.type==\'Microsoft.ApiManagement/service/api-version-sets\')]") .FirstOrDefault(x => x.Value<string>("name").Contains(versionSetId)); if (versionSet != null) { template.parameters = GetParameters(parsedTemplate["parameters"], versionSet); template.resources.Add(apiStandalone ? RemoveServiceDependencies(versionSet) : JObject.FromObject(versionSet)); } generatedTemplate.Content = JObject.FromObject(template); return generatedTemplate; } private GeneratedTemplate GenerateAPI(JToken api, JObject parsedTemplate, bool apiStandalone, bool separatePolicyFile) { GeneratedTemplate generatedTemplate = new GeneratedTemplate(); DeploymentTemplate template = new DeploymentTemplate(true, true); if (separatePolicyFile) { ReplaceApiOperationPolictPolicyWithFileLink(api, parsedTemplate); AddParametersForFileLink(parsedTemplate); } template.parameters = GetParameters(parsedTemplate["parameters"], api); SetFilenameAndDirectory(api, parsedTemplate, generatedTemplate); template.resources.Add(apiStandalone ? RemoveServiceDependencies(api) : JObject.FromObject(api)); if (apiStandalone) AddProductAPI(api, parsedTemplate, template.resources); generatedTemplate.Content = JObject.FromObject(template); return generatedTemplate; } private void AddProductAPI(JToken api, JObject parsedTemplate, IList<JObject> templateResources) { string apiName = GetParameterPart(api, "name", -2); if (apiName.StartsWith("/")) apiName = apiName.Substring(1, apiName.Length - 1); var productApi = parsedTemplate.SelectTokens($"$..resources[?(@.type=='{ProductAPIResourceType}')]") .FirstOrDefault(p => GetParameterPart(p, "name", -2) == apiName); if (productApi != null) { var dependsOn = productApi.Value<JArray>("") ?? new JArray(); var serviceName = GetParameterPart(api, "name", -4); dependsOn.Add($"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{serviceName}'),'{apiName}')]"); productApi["dependsOn"] = dependsOn; templateResources.Add(JObject.FromObject(productApi)); } } private static JObject RemoveServiceDependencies(JToken api) { JObject item = JObject.FromObject(api); var dependsOn = item.SelectTokens("$..dependsOn[*]").Where(token => token.Value<string>().StartsWith("[resourceId('Microsoft.ApiManagement/service'")).ToList(); dependsOn.ForEach(token => token.Remove()); return item; } private static void SetFilenameAndDirectory(JToken api, JObject parsedTemplate, GeneratedTemplate generatedTemplate) { var filenameAndDirectory = GetFileNameAndDirectory(api, parsedTemplate); generatedTemplate.FileName = filenameAndDirectory.FileName; generatedTemplate.Directory = filenameAndDirectory.Directory; } private static FileInfo GetFilenameAndDirectoryForOperationPolicy(JToken api, JObject parsedTemplate, string operationId) { var fileInfo = GetFileNameAndDirectory(api, parsedTemplate); fileInfo.FileName = fileInfo.FileName.Replace(".template.json", String.IsNullOrWhiteSpace(operationId) ? ".policy.xml" : $".{operationId}.policy.xml"); return fileInfo; } private static FileInfo GetFileNameAndDirectory(JToken api, JObject parsedTemplate) { string filename, directory; if (api["properties"]["apiVersionSetId"] != null) { string versionSetName = GetVersionSetName(api, parsedTemplate); string version = GetApiVersion(api, parsedTemplate); filename = $"api-{versionSetName}.{version}.template.json"; directory = $@"api-{versionSetName}\{version}"; return new FileInfo(filename, directory); } string name = api["properties"].Value<string>("displayName").Replace(' ', '-'); filename = $"api-{name}.template.json"; directory = $"api-{name}"; return new FileInfo(filename, directory); } private static void SetFilenameAndDirectoryForVersionSet(JToken api, GeneratedTemplate generatedTemplate, JObject parsedTemplate) { string versionSetName = GetVersionSetName(api, parsedTemplate); generatedTemplate.FileName = $"api-{versionSetName}.version-set.template.json"; generatedTemplate.Directory = $@"api-{versionSetName}"; } private static string GetApiVersion(JToken api, JObject parsedTemplate) { if (api["properties"]["apiVersion"] == null) return "default"; var apiVersion = GetParameterPart(api["properties"], "apiVersion", -2); var jpath = $"$.parameters.{apiVersion}.defaultValue"; var version = parsedTemplate.SelectToken(jpath).Value<string>(); return version; } private static string GetVersionSetName(JToken api, JObject parsedTemplate) { JToken apivs = GetVersionSet(api, parsedTemplate); var versionSetName = apivs["properties"].Value<string>("displayName"); var formattedVersionSetName = versionSetName.Replace(' ', '-'); return formattedVersionSetName; } private static JToken GetVersionSet(JToken api, JObject parsedTemplate) { var versionSetId = GetParameterPart(api["properties"], "apiVersionSetId", -2); var apivs = parsedTemplate .SelectTokens("$.resources[?(@.type=='Microsoft.ApiManagement/service/api-version-sets')]") .FirstOrDefault(x => x.Value<string>("name").Contains(versionSetId)); return apivs; } private static string GetParameterPart(JToken jToken, string name, int index, char separator = '\'') { var value = jToken.Value<string>(name); return GetSplitPart(index, value, separator); } private static string GetSplitPart(int index, string value, char separator = '\'') { string[] split = value.Split(separator); if (index > split.Length - 1 || index < -1 * split.Length) return String.Empty; if (index >= 0) return split[index]; var length = split.Length; return split[length + index]; } private static JObject GetParameters(JToken parameters, JToken api) { var regExp = new Regex("parameters\\('(?<parameter>.+?)'\\)"); MatchCollection matches = regExp.Matches(api.ToString()); IEnumerable<string> usedParameters = matches.Cast<Match>().Select(x => x.Groups["parameter"].Value).Distinct(); IEnumerable<JProperty> filteredParameters = parameters.Cast<JProperty>().Where(x => usedParameters.Contains(x.Name)); return new JObject(filteredParameters); } } } |