private string GetValidLoggerParamName(string resourceName) { string[] loggerNameStrs = resourceName.Split(new char[] { ',' }); string validLoggerName = ExtractorUtils.GenValidParamName(loggerNameStrs[loggerNameStrs.Length - 1], ParameterPrefix.LogResourceId); return(validLoggerName); }
// this function generate all reference loggers in all extracted apis public static async Task <Dictionary <string, object> > GetAllReferencedLoggers(List <string> apisToExtract, Extractor exc) { Dictionary <string, object> ApiLoggerId = new Dictionary <string, object>(); APIExtractor apiExc = new APIExtractor(new FileWriter()); string serviceDiagnostics = await apiExc.GetServiceDiagnosticsAsync(exc.sourceApimName, exc.resourceGroup); JObject oServiceDiagnostics = JObject.Parse(serviceDiagnostics); Dictionary <string, string> serviceloggerIds = new Dictionary <string, string>(); foreach (var serviceDiagnostic in oServiceDiagnostics["value"]) { string diagnosticName = ((JValue)serviceDiagnostic["name"]).Value.ToString(); string loggerId = ((JValue)serviceDiagnostic["properties"]["loggerId"]).Value.ToString(); ApiLoggerId.Add(ExtractorUtils.GenValidParamName(diagnosticName, ParameterPrefix.Diagnostic), loggerId); } foreach (string curApiName in apisToExtract) { Dictionary <string, string> loggerIds = new Dictionary <string, string>(); string diagnostics = await apiExc.GetAPIDiagnosticsAsync(exc.sourceApimName, exc.resourceGroup, curApiName); JObject oDiagnostics = JObject.Parse(diagnostics); foreach (var diagnostic in oDiagnostics["value"]) { string diagnosticName = ((JValue)diagnostic["name"]).Value.ToString(); string loggerId = ((JValue)diagnostic["properties"]["loggerId"]).Value.ToString(); loggerIds.Add(ExtractorUtils.GenValidParamName(diagnosticName, ParameterPrefix.Diagnostic), loggerId); } if (loggerIds.Count != 0) { ApiLoggerId.Add(ExtractorUtils.GenValidParamName(curApiName, ParameterPrefix.Api), loggerIds); } } return(ApiLoggerId); }
public async Task <Template> GenerateNamedValuesTemplateAsync(string singleApiName, List <TemplateResource> apiTemplateResources, Extractor exc) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting named values from service"); Template armTemplate = GenerateEmptyPropertyTemplateWithParameters(exc); List <TemplateResource> templateResources = new List <TemplateResource>(); // pull all named values (properties) for service string properties = await GetPropertiesAsync(exc.sourceApimName, exc.resourceGroup); JObject oProperties = JObject.Parse(properties); foreach (var extractedProperty in oProperties["value"]) { string propertyName = ((JValue)extractedProperty["name"]).Value.ToString(); string fullPropertyResource = await GetPropertyDetailsAsync(exc.sourceApimName, exc.resourceGroup, propertyName); // convert returned named value to template resource class PropertyTemplateResource propertyTemplateResource = JsonConvert.DeserializeObject <PropertyTemplateResource>(fullPropertyResource); propertyTemplateResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{propertyName}')]"; propertyTemplateResource.type = ResourceTypeConstants.Property; propertyTemplateResource.apiVersion = GlobalConstants.ServicePropertyAPIVersion; propertyTemplateResource.scale = null; if (exc.paramNamedValue) { propertyTemplateResource.properties.value = $"[parameters('{ParameterNames.NamedValues}').{ExtractorUtils.GenValidParamName(propertyName, ParameterPrefix.Property)}]"; } if (singleApiName == null) { // if the user is executing a full extraction, extract all the loggers Console.WriteLine("'{0}' Named value found", propertyName); templateResources.Add(propertyTemplateResource); } else { // TODO - if the user is executing a single api, extract all the named values used in the template resources Console.WriteLine("'{0}' Named value found", propertyName); templateResources.Add(propertyTemplateResource); } } armTemplate.resources = templateResources.ToArray(); return(armTemplate); }
// this function will get the current revision of this api and will remove "isCurrent" paramter public async Task <List <TemplateResource> > GenerateCurrentRevisionAPIResourceAsync(string apiName, Extractor exc) { List <TemplateResource> templateResources = new List <TemplateResource>(); string apimname = exc.sourceApimName, resourceGroup = exc.resourceGroup, fileFolder = exc.fileFolder, policyXMLBaseUrl = exc.policyXMLBaseUrl, policyXMLSasToken = exc.policyXMLSasToken; string apiDetails = await GetAPIDetailsAsync(apimname, resourceGroup, apiName); Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting resources from {0} API:", apiName); // convert returned api to template resource class JObject oApiDetails = JObject.Parse(apiDetails); APITemplateResource apiResource = JsonConvert.DeserializeObject <APITemplateResource>(apiDetails); apiResource.type = ((JValue)oApiDetails["type"]).Value.ToString(); apiResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}')]"; apiResource.apiVersion = GlobalConstants.APIVersion; apiResource.scale = null; apiResource.properties.isCurrent = null; if (exc.paramServiceUrl) { apiResource.properties.serviceUrl = $"[parameters('{ParameterNames.ServiceUrl}').{ExtractorUtils.GenValidParamName(apiName, ParameterPrefix.Api)}]"; } if (apiResource.properties.apiVersionSetId != null) { apiResource.dependsOn = new string[] { }; string versionSetName = apiResource.properties.apiVersionSetId; int versionSetPosition = versionSetName.IndexOf("apiVersionSets/"); versionSetName = versionSetName.Substring(versionSetPosition, (versionSetName.Length - versionSetPosition)); apiResource.properties.apiVersionSetId = $"[concat(resourceId('Microsoft.ApiManagement/service', parameters('{ParameterNames.ApimServiceName}')), '/{versionSetName}')]"; } else { apiResource.dependsOn = new string[] { }; } templateResources.Add(apiResource); #region Schemas // add schema resources to api template List <TemplateResource> schemaResources = await GenerateSchemasARMTemplate(apimname, apiName, resourceGroup, fileFolder); templateResources.AddRange(schemaResources); #endregion #region Operations // pull api operations for service string[] operationNames = await GetAllOperationNames(apimname, resourceGroup, apiName); foreach (string operationName in operationNames) { string operationDetails = await GetAPIOperationDetailsAsync(apimname, resourceGroup, apiName, operationName); Console.WriteLine("'{0}' Operation found", operationName); // convert returned operation to template resource class OperationTemplateResource operationResource = JsonConvert.DeserializeObject <OperationTemplateResource>(operationDetails); string operationResourceName = operationResource.name; operationResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{operationResourceName}')]"; operationResource.apiVersion = GlobalConstants.APIVersion; operationResource.scale = null; // add operation dependencies and fix sample value if necessary List <string> operationDependsOn = new List <string>() { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; foreach (OperationTemplateRepresentation operationTemplateRepresentation in operationResource.properties.request.representations) { AddSchemaDependencyToOperationIfNecessary(apiName, operationDependsOn, operationTemplateRepresentation); ArmEscapeSampleValueIfNecessary(operationTemplateRepresentation); } foreach (OperationsTemplateResponse operationTemplateResponse in operationResource.properties.responses) { foreach (OperationTemplateRepresentation operationTemplateRepresentation in operationTemplateResponse.representations) { AddSchemaDependencyToOperationIfNecessary(apiName, operationDependsOn, operationTemplateRepresentation); ArmEscapeSampleValueIfNecessary(operationTemplateRepresentation); } } operationResource.dependsOn = operationDependsOn.ToArray(); templateResources.Add(operationResource); // add operation policy resource to api template try { string operationPolicy = await GetOperationPolicyAsync(apimname, resourceGroup, apiName, operationName); Console.WriteLine($" - Operation policy found for {operationName} operation"); PolicyTemplateResource operationPolicyResource = JsonConvert.DeserializeObject <PolicyTemplateResource>(operationPolicy); operationPolicyResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{operationResourceName}/policy')]"; operationPolicyResource.apiVersion = GlobalConstants.APIVersion; operationPolicyResource.scale = null; operationPolicyResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{ParameterNames.ApimServiceName}'), '{apiName}', '{operationResourceName}')]" }; // write policy xml content to file and point to it if policyXMLBaseUrl is provided if (policyXMLBaseUrl != null) { string policyXMLContent = operationPolicyResource.properties.value; string policyFolder = String.Concat(fileFolder, $@"/policies"); string operationPolicyFileName = $@"/{apiName}-{operationName}-operationPolicy.xml"; this.fileWriter.CreateFolderIfNotExists(policyFolder); this.fileWriter.WriteXMLToFile(policyXMLContent, String.Concat(policyFolder, operationPolicyFileName)); operationPolicyResource.properties.format = "rawxml-link"; if (policyXMLSasToken != null) { operationPolicyResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{operationPolicyFileName}', parameters('{ParameterNames.PolicyXMLSasToken}'))]"; } else { operationPolicyResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{operationPolicyFileName}')]"; } } templateResources.Add(operationPolicyResource); } catch (Exception) { } // add tags associated with the operation to template try { // pull tags associated with the operation string apiOperationTags = await GetOperationTagsAsync(apimname, resourceGroup, apiName, operationName); JObject oApiOperationTags = JObject.Parse(apiOperationTags); foreach (var tag in oApiOperationTags["value"]) { string apiOperationTagName = ((JValue)tag["name"]).Value.ToString(); Console.WriteLine(" - '{0}' Tag association found for {1} operation", apiOperationTagName, operationResourceName); // convert operation tag association to template resource class TagTemplateResource operationTagResource = JsonConvert.DeserializeObject <TagTemplateResource>(tag.ToString()); operationTagResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{operationResourceName}/{apiOperationTagName}')]"; operationTagResource.apiVersion = GlobalConstants.APIVersion; operationTagResource.scale = null; operationTagResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{ParameterNames.ApimServiceName}'), '{apiName}', '{operationResourceName}')]" }; templateResources.Add(operationTagResource); } } catch (Exception) { } } #endregion #region API Policies // add api policy resource to api template try { string apiPolicies = await GetAPIPolicyAsync(apimname, resourceGroup, apiName); Console.WriteLine("API policy found"); PolicyTemplateResource apiPoliciesResource = JsonConvert.DeserializeObject <PolicyTemplateResource>(apiPolicies); apiPoliciesResource.apiVersion = GlobalConstants.APIVersion; apiPoliciesResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{apiPoliciesResource.name}')]"; apiPoliciesResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; // write policy xml content to file and point to it if policyXMLBaseUrl is provided if (policyXMLBaseUrl != null) { string policyXMLContent = apiPoliciesResource.properties.value; string policyFolder = String.Concat(fileFolder, $@"/policies"); string apiPolicyFileName = $@"/{apiName}-apiPolicy.xml"; this.fileWriter.CreateFolderIfNotExists(policyFolder); this.fileWriter.WriteXMLToFile(policyXMLContent, String.Concat(policyFolder, apiPolicyFileName)); apiPoliciesResource.properties.format = "rawxml-link"; if (policyXMLSasToken != null) { apiPoliciesResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{apiPolicyFileName}', parameters('{ParameterNames.PolicyXMLSasToken}'))]"; } else { apiPoliciesResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{apiPolicyFileName}')]"; } } templateResources.Add(apiPoliciesResource); } catch (Exception) { } #endregion // add tags associated with the api to template try { // pull tags associated with the api string apiTags = await GetAPITagsAsync(apimname, resourceGroup, apiName); JObject oApiTags = JObject.Parse(apiTags); foreach (var tag in oApiTags["value"]) { string apiTagName = ((JValue)tag["name"]).Value.ToString(); Console.WriteLine("'{0}' Tag association found", apiTagName); // convert associations between api and tags to template resource class TagTemplateResource apiTagResource = JsonConvert.DeserializeObject <TagTemplateResource>(tag.ToString()); apiTagResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{apiTagName}')]"; apiTagResource.apiVersion = GlobalConstants.APIVersion; apiTagResource.scale = null; apiTagResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; templateResources.Add(apiTagResource); } } catch (Exception) { } // add product api associations to template #region API Products try { // pull product api associations string apiProducts = await GetAPIProductsAsync(apimname, resourceGroup, apiName); JObject oApiProducts = JObject.Parse(apiProducts); foreach (var item in oApiProducts["value"]) { string apiProductName = ((JValue)item["name"]).Value.ToString(); Console.WriteLine("'{0}' Product association found", apiProductName); // convert returned api product associations to template resource class ProductAPITemplateResource productAPIResource = JsonConvert.DeserializeObject <ProductAPITemplateResource>(item.ToString()); productAPIResource.type = ResourceTypeConstants.ProductAPI; productAPIResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiProductName}/{apiName}')]"; productAPIResource.apiVersion = GlobalConstants.APIVersion; productAPIResource.scale = null; productAPIResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; templateResources.Add(productAPIResource); } } catch (Exception) { } #endregion #region Diagnostics // add diagnostics to template // pull diagnostics for api string diagnostics = await GetAPIDiagnosticsAsync(apimname, resourceGroup, apiName); JObject oDiagnostics = JObject.Parse(diagnostics); foreach (var diagnostic in oDiagnostics["value"]) { string diagnosticName = ((JValue)diagnostic["name"]).Value.ToString(); Console.WriteLine("'{0}' Diagnostic found", diagnosticName); // convert returned diagnostic to template resource class DiagnosticTemplateResource diagnosticResource = diagnostic.ToObject <DiagnosticTemplateResource>(); diagnosticResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{diagnosticName}')]"; diagnosticResource.type = ResourceTypeConstants.APIDiagnostic; diagnosticResource.apiVersion = GlobalConstants.APIVersion; diagnosticResource.scale = null; diagnosticResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; if (exc.paramApiLoggerId) { diagnosticResource.properties.loggerId = $"[parameters('{ParameterNames.ApiLoggerId}').{ExtractorUtils.GenValidParamName(apiName, ParameterPrefix.Api)}.{ExtractorUtils.GenValidParamName(diagnosticName, ParameterPrefix.Diagnostic)}]"; } if (!diagnosticName.Contains("applicationinsights")) { // enableHttpCorrelationHeaders only works for application insights, causes errors otherwise diagnosticResource.properties.enableHttpCorrelationHeaders = null; } templateResources.Add(diagnosticResource); } #endregion return(templateResources); }
public async Task <Template> GenerateLoggerTemplateAsync(Extractor exc, string singleApiName, List <TemplateResource> apiTemplateResources, Dictionary <string, Dictionary <string, string> > apiLoggerId) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting loggers from service"); Template armTemplate = GenerateEmptyLoggerTemplateWithParameters(exc); // isolate product api associations in the case of a single api extraction var policyResources = apiTemplateResources.Where(resource => (resource.type == ResourceTypeConstants.APIPolicy || resource.type == ResourceTypeConstants.APIOperationPolicy || resource.type == ResourceTypeConstants.ProductPolicy)); List <TemplateResource> templateResources = new List <TemplateResource>(); // pull all loggers for service string loggers = await GetLoggersAsync(exc.sourceApimName, exc.resourceGroup); JObject oLoggers = JObject.Parse(loggers); foreach (var extractedLogger in oLoggers["value"]) { string loggerName = ((JValue)extractedLogger["name"]).Value.ToString(); string fullLoggerResource = await GetLoggerDetailsAsync(exc.sourceApimName, exc.resourceGroup, loggerName); // convert returned logger to template resource class LoggerTemplateResource loggerResource = JsonConvert.DeserializeObject <LoggerTemplateResource>(fullLoggerResource); loggerResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{loggerName}')]"; loggerResource.type = ResourceTypeConstants.Logger; loggerResource.apiVersion = GlobalConstants.APIVersion; loggerResource.scale = null; if (singleApiName == null) { // if the user is extracting all apis, extract all the loggers Console.WriteLine("'{0}' Logger found", loggerName); templateResources.Add(loggerResource); } else { // if the user is extracting a single api, extract the loggers referenced by its diagnostics and api policies bool isReferencedInPolicy = false; bool isReferencedInDiagnostic = false; foreach (PolicyTemplateResource policyTemplateResource in policyResources) { if (policyTemplateResource.properties.value.Contains(loggerName)) { isReferencedInPolicy = true; } } string validApiName = ExtractorUtils.GenValidParamName(singleApiName, ParameterPrefix.Api); if (exc.paramApiLoggerId && apiLoggerId.ContainsKey(validApiName)) { Dictionary <string, string> curDiagnostic = apiLoggerId[validApiName]; string validDName = ExtractorUtils.GenValidParamName(loggerResource.properties.loggerType, ParameterPrefix.Diagnostic).ToLower(); if (curDiagnostic.ContainsKey(validDName) && curDiagnostic[validDName].Contains(loggerName)) { isReferencedInDiagnostic = true; } } if (isReferencedInPolicy == true || isReferencedInDiagnostic == true) { // logger was used in policy or diagnostic, extract it Console.WriteLine("'{0}' Logger found", loggerName); templateResources.Add(loggerResource); } }; } armTemplate.resources = templateResources.ToArray(); return(armTemplate); }
// this function will get the current revision of this api and will remove "isCurrent" paramter public async Task <List <TemplateResource> > GenerateCurrentRevisionAPIResourceAsync(string apiName, Extractor exc) { List <TemplateResource> templateResources = new List <TemplateResource>(); string apimname = exc.sourceApimName, resourceGroup = exc.resourceGroup, fileFolder = exc.fileFolder, policyXMLBaseUrl = exc.policyXMLBaseUrl, policyXMLSasToken = exc.policyXMLSasToken; string apiDetails = await GetAPIDetailsAsync(apimname, resourceGroup, apiName); Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting resources from {0} API:", apiName); // convert returned api to template resource class JObject oApiDetails = JObject.Parse(apiDetails); APITemplateResource apiResource = JsonConvert.DeserializeObject <APITemplateResource>(apiDetails); apiResource.type = ((JValue)oApiDetails["type"]).Value.ToString(); apiResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}')]"; apiResource.apiVersion = GlobalConstants.APIVersion; apiResource.scale = null; apiResource.properties.isCurrent = null; if (exc.paramServiceUrl) { apiResource.properties.serviceUrl = $"[parameters('{ParameterNames.ServiceUrl}').{ExtractorUtils.GenValidParamName(apiName, ParameterPrefix.Api)}]"; } if (apiResource.properties.apiVersionSetId != null) { apiResource.dependsOn = new string[] { }; string versionSetName = apiResource.properties.apiVersionSetId; int versionSetPosition = versionSetName.IndexOf("apiVersionSets/"); versionSetName = versionSetName.Substring(versionSetPosition, (versionSetName.Length - versionSetPosition)); apiResource.properties.apiVersionSetId = $"[concat(resourceId('Microsoft.ApiManagement/service', parameters('{ParameterNames.ApimServiceName}')), '/{versionSetName}')]"; } else { apiResource.dependsOn = new string[] { }; } templateResources.Add(apiResource); templateResources.AddRange(await GetRelatedTemplateResourcesAsync(apiName, exc)); return(templateResources); }
/// <summary> /// Gets the "All API" level diagnostic resources, these are common to all APIs. /// </summary> /// <param name="exc">The extractor.</param> /// <returns>a list of DiagnosticTemplateResources</returns> private async Task <IEnumerable <TemplateResource> > GetServiceDiagnosticsTemplateResourcesAsync(Extractor exc) { List <TemplateResource> templateResources = new List <TemplateResource>(); string apimname = exc.sourceApimName, resourceGroup = exc.resourceGroup; string serviceDiagnostics = await GetServiceDiagnosticsAsync(apimname, resourceGroup); JObject oServiceDiagnostics = JObject.Parse(serviceDiagnostics); foreach (var serviceDiagnostic in oServiceDiagnostics["value"]) { string serviceDiagnosticName = ((JValue)serviceDiagnostic["name"]).Value.ToString(); Console.WriteLine("'{0}' Diagnostic found", serviceDiagnosticName); // convert returned diagnostic to template resource class DiagnosticTemplateResource serviceDiagnosticResource = serviceDiagnostic.ToObject <DiagnosticTemplateResource>(); serviceDiagnosticResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{serviceDiagnosticName}')]"; serviceDiagnosticResource.type = ResourceTypeConstants.APIServiceDiagnostic; serviceDiagnosticResource.apiVersion = GlobalConstants.APIVersion; serviceDiagnosticResource.scale = null; serviceDiagnosticResource.dependsOn = new string[] { }; if (exc.paramApiLoggerId) { serviceDiagnosticResource.properties.loggerId = $"[parameters('{ParameterNames.ApiLoggerId}').{ExtractorUtils.GenValidParamName(serviceDiagnosticName, ParameterPrefix.Diagnostic)}]"; } if (!serviceDiagnosticName.Contains("applicationinsights")) { // enableHttpCorrelationHeaders only works for application insights, causes errors otherwise //TODO: Check this settings still valid? serviceDiagnosticResource.properties.enableHttpCorrelationHeaders = null; } templateResources.Add(serviceDiagnosticResource); } return(templateResources.ToArray()); }
/// <summary> /// Adds related API Template resources like schemas, operations, products, tags etc. /// </summary> /// <param name="apiName">The name of the API.</param> /// <param name="exc">The extractor.</param> /// <returns></returns> private async Task <IEnumerable <TemplateResource> > GetRelatedTemplateResourcesAsync(string apiName, Extractor exc) { List <TemplateResource> templateResources = new List <TemplateResource>(); string apimname = exc.sourceApimName, resourceGroup = exc.resourceGroup, fileFolder = exc.fileFolder, policyXMLBaseUrl = exc.policyXMLBaseUrl, policyXMLSasToken = exc.policyXMLSasToken; #region Schemas // add schema resources to api template List <TemplateResource> schemaResources = await GenerateSchemasARMTemplate(apimname, apiName, resourceGroup, fileFolder); templateResources.AddRange(schemaResources); #endregion #region Operations // pull api operations for service string[] operationNames = await GetAllOperationNames(apimname, resourceGroup, apiName); int numBatches = 0; // create empty array for the batch operation owners List <string> batchOwners = new List <string>(); // if a batch size is specified if (exc.operationBatchSize > 0) { // store the number of batches required based on exc.operationBatchSize numBatches = (int)Math.Ceiling((double)operationNames.Length / (double)exc.operationBatchSize); //Console.WriteLine ("Number of batches: {0}", numBatches); } foreach (string operationName in operationNames) { int opIndex = Array.IndexOf(operationNames, operationName); //add batch owners into array // ensure each owner is linked to the one before if (exc.operationBatchSize > 0 && opIndex < numBatches) { batchOwners.Add(operationName); //Console.WriteLine("Adding operation {0} to owner list", operationName); } string operationDetails = await GetAPIOperationDetailsAsync(apimname, resourceGroup, apiName, operationName); Console.WriteLine("'{0}' Operation found", operationName); // convert returned operation to template resource class OperationTemplateResource operationResource = JsonConvert.DeserializeObject <OperationTemplateResource>(operationDetails); string operationResourceName = operationResource.name; operationResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{operationResourceName}')]"; operationResource.apiVersion = GlobalConstants.APIVersion; operationResource.scale = null; // add operation dependencies and fix sample value if necessary List <string> operationDependsOn = new List <string>() { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; foreach (OperationTemplateRepresentation operationTemplateRepresentation in operationResource.properties.request.representations) { AddSchemaDependencyToOperationIfNecessary(apiName, operationDependsOn, operationTemplateRepresentation); ArmEscapeSampleValueIfNecessary(operationTemplateRepresentation); } foreach (OperationsTemplateResponse operationTemplateResponse in operationResource.properties.responses) { foreach (OperationTemplateRepresentation operationTemplateRepresentation in operationTemplateResponse.representations) { AddSchemaDependencyToOperationIfNecessary(apiName, operationDependsOn, operationTemplateRepresentation); ArmEscapeSampleValueIfNecessary(operationTemplateRepresentation); } } // add to batch if flagged string batchdependsOn; if (exc.operationBatchSize > 0 && opIndex > 0) { if (opIndex >= 1 && opIndex <= numBatches - 1) { // chain the owners to each other batchdependsOn = $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{ParameterNames.ApimServiceName}'), '{apiName}', '{batchOwners[opIndex - 1]}')]"; //Console.WriteLine("Owner chaining: this request {0} to previous {1}", operationName, batchOwners[opIndex-1]); } else { // chain the operation to respective owner int ownerIndex = (int)Math.Floor((opIndex - numBatches) / ((double)exc.operationBatchSize - 1)); batchdependsOn = $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{ParameterNames.ApimServiceName}'), '{apiName}', '{batchOwners[ownerIndex]}')]"; //Console.WriteLine("Operation {0} chained to owner {1}", operationName, batchOwners[ownerIndex]); } operationDependsOn.Add(batchdependsOn); } operationResource.dependsOn = operationDependsOn.ToArray(); templateResources.Add(operationResource); // add operation policy resource to api template try { string operationPolicy = await GetOperationPolicyAsync(apimname, resourceGroup, apiName, operationName); Console.WriteLine($" - Operation policy found for {operationName} operation"); PolicyTemplateResource operationPolicyResource = JsonConvert.DeserializeObject <PolicyTemplateResource>(operationPolicy); operationPolicyResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{operationResourceName}/policy')]"; operationPolicyResource.apiVersion = GlobalConstants.APIVersion; operationPolicyResource.scale = null; operationPolicyResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{ParameterNames.ApimServiceName}'), '{apiName}', '{operationResourceName}')]" }; // write policy xml content to file and point to it if policyXMLBaseUrl is provided if (policyXMLBaseUrl != null) { string policyXMLContent = operationPolicyResource.properties.value; string policyFolder = String.Concat(fileFolder, $@"/policies"); string operationPolicyFileName = $@"/{apiName}-{operationName}-operationPolicy.xml"; this.fileWriter.CreateFolderIfNotExists(policyFolder); this.fileWriter.WriteXMLToFile(policyXMLContent, String.Concat(policyFolder, operationPolicyFileName)); operationPolicyResource.properties.format = "rawxml-link"; if (policyXMLSasToken != null) { operationPolicyResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{operationPolicyFileName}', parameters('{ParameterNames.PolicyXMLSasToken}'))]"; } else { operationPolicyResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{operationPolicyFileName}')]"; } } templateResources.Add(operationPolicyResource); } catch (Exception) { } // add tags associated with the operation to template try { // pull tags associated with the operation string apiOperationTags = await GetOperationTagsAsync(apimname, resourceGroup, apiName, operationName); JObject oApiOperationTags = JObject.Parse(apiOperationTags); foreach (var tag in oApiOperationTags["value"]) { string apiOperationTagName = ((JValue)tag["name"]).Value.ToString(); Console.WriteLine(" - '{0}' Tag association found for {1} operation", apiOperationTagName, operationResourceName); // convert operation tag association to template resource class TagTemplateResource operationTagResource = JsonConvert.DeserializeObject <TagTemplateResource>(tag.ToString()); operationTagResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{operationResourceName}/{apiOperationTagName}')]"; operationTagResource.apiVersion = GlobalConstants.APIVersion; operationTagResource.scale = null; operationTagResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{ParameterNames.ApimServiceName}'), '{apiName}', '{operationResourceName}')]" }; templateResources.Add(operationTagResource); } } catch (Exception) { } } #endregion #region API Policies // add api policy resource to api template try { string apiPolicies = await GetAPIPolicyAsync(apimname, resourceGroup, apiName); Console.WriteLine("API policy found"); PolicyTemplateResource apiPoliciesResource = JsonConvert.DeserializeObject <PolicyTemplateResource>(apiPolicies); apiPoliciesResource.apiVersion = GlobalConstants.APIVersion; apiPoliciesResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{apiPoliciesResource.name}')]"; apiPoliciesResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; // write policy xml content to file and point to it if policyXMLBaseUrl is provided if (policyXMLBaseUrl != null) { string policyXMLContent = apiPoliciesResource.properties.value; string policyFolder = String.Concat(fileFolder, $@"/policies"); string apiPolicyFileName = $@"/{apiName}-apiPolicy.xml"; this.fileWriter.CreateFolderIfNotExists(policyFolder); this.fileWriter.WriteXMLToFile(policyXMLContent, String.Concat(policyFolder, apiPolicyFileName)); apiPoliciesResource.properties.format = "rawxml-link"; if (policyXMLSasToken != null) { apiPoliciesResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{apiPolicyFileName}', parameters('{ParameterNames.PolicyXMLSasToken}'))]"; } else { apiPoliciesResource.properties.value = $"[concat(parameters('{ParameterNames.PolicyXMLBaseUrl}'), '{apiPolicyFileName}')]"; } } templateResources.Add(apiPoliciesResource); } catch (Exception) { } #endregion #region API Tags // add tags associated with the api to template try { // pull tags associated with the api string apiTags = await GetAPITagsAsync(apimname, resourceGroup, apiName); JObject oApiTags = JObject.Parse(apiTags); foreach (var tag in oApiTags["value"]) { string apiTagName = ((JValue)tag["name"]).Value.ToString(); Console.WriteLine("'{0}' Tag association found", apiTagName); // convert associations between api and tags to template resource class TagTemplateResource apiTagResource = JsonConvert.DeserializeObject <TagTemplateResource>(tag.ToString()); apiTagResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{apiTagName}')]"; apiTagResource.apiVersion = GlobalConstants.APIVersion; apiTagResource.scale = null; apiTagResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; templateResources.Add(apiTagResource); } } catch (Exception) { } #endregion // add product api associations to template #region API Products try { // pull product api associations string apiProducts = await GetAPIProductsAsync(apimname, resourceGroup, apiName); JObject oApiProducts = JObject.Parse(apiProducts); foreach (var item in oApiProducts["value"]) { string apiProductName = ((JValue)item["name"]).Value.ToString(); Console.WriteLine("'{0}' Product association found", apiProductName); // convert returned api product associations to template resource class ProductAPITemplateResource productAPIResource = JsonConvert.DeserializeObject <ProductAPITemplateResource>(item.ToString()); productAPIResource.type = ResourceTypeConstants.ProductAPI; productAPIResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiProductName}/{apiName}')]"; productAPIResource.apiVersion = GlobalConstants.APIVersion; productAPIResource.scale = null; productAPIResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; templateResources.Add(productAPIResource); } } catch (Exception) { } #endregion #region Diagnostics // add diagnostics to template // pull diagnostics for api string diagnostics = await GetAPIDiagnosticsAsync(apimname, resourceGroup, apiName); JObject oDiagnostics = JObject.Parse(diagnostics); foreach (var diagnostic in oDiagnostics["value"]) { string diagnosticName = ((JValue)diagnostic["name"]).Value.ToString(); Console.WriteLine("'{0}' Diagnostic found", diagnosticName); // convert returned diagnostic to template resource class DiagnosticTemplateResource diagnosticResource = diagnostic.ToObject <DiagnosticTemplateResource>(); diagnosticResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{apiName}/{diagnosticName}')]"; diagnosticResource.type = ResourceTypeConstants.APIDiagnostic; diagnosticResource.apiVersion = GlobalConstants.APIVersion; diagnosticResource.scale = null; diagnosticResource.dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{apiName}')]" }; if (exc.paramApiLoggerId) { diagnosticResource.properties.loggerId = $"[parameters('{ParameterNames.ApiLoggerId}').{ExtractorUtils.GenValidParamName(apiName, ParameterPrefix.Api)}.{ExtractorUtils.GenValidParamName(diagnosticName, ParameterPrefix.Diagnostic)}]"; } if (!diagnosticName.Contains("applicationinsights")) { // enableHttpCorrelationHeaders only works for application insights, causes errors otherwise diagnosticResource.properties.enableHttpCorrelationHeaders = null; } templateResources.Add(diagnosticResource); } #endregion return(templateResources); }
public async Task <Template> CreateMasterTemplateParameterValues(List <string> apisToExtract, Extractor exc, Dictionary <string, Dictionary <string, string> > apiLoggerId, Dictionary <string, string> loggerResourceIds) { // used to create the parameter values for use in parameters file // create empty template Template masterTemplate = GenerateEmptyTemplate(); // add parameters with value property Dictionary <string, TemplateParameterProperties> parameters = new Dictionary <string, TemplateParameterProperties>(); TemplateParameterProperties apimServiceNameProperties = new TemplateParameterProperties() { value = exc.destinationApimName }; parameters.Add(ParameterNames.ApimServiceName, apimServiceNameProperties); if (exc.linkedTemplatesBaseUrl != null) { TemplateParameterProperties linkedTemplatesBaseUrlProperties = new TemplateParameterProperties() { value = exc.linkedTemplatesBaseUrl }; parameters.Add(ParameterNames.LinkedTemplatesBaseUrl, linkedTemplatesBaseUrlProperties); // add linkedTemplatesSasToken parameter if provided and if the user has provided a linkedTemplatesBaseUrl if (exc.linkedTemplatesSasToken != null) { TemplateParameterProperties linkedTemplatesSasTokenProperties = new TemplateParameterProperties() { value = exc.linkedTemplatesSasToken }; parameters.Add(ParameterNames.LinkedTemplatesSasToken, linkedTemplatesSasTokenProperties); } // add linkedTemplatesUrlQueryString parameter if provided and if the user has provided a linkedTemplatesBaseUrl if (exc.linkedTemplatesUrlQueryString != null) { TemplateParameterProperties linkedTemplatesUrlQueryStringProperties = new TemplateParameterProperties() { value = exc.linkedTemplatesUrlQueryString }; parameters.Add(ParameterNames.LinkedTemplatesUrlQueryString, linkedTemplatesUrlQueryStringProperties); } } if (exc.policyXMLBaseUrl != null) { TemplateParameterProperties policyTemplateBaseUrlProperties = new TemplateParameterProperties() { value = exc.policyXMLBaseUrl }; parameters.Add(ParameterNames.PolicyXMLBaseUrl, policyTemplateBaseUrlProperties); // add policyXMLSasToken parameter if provided and if the user has provided a policyXMLBaseUrl if (exc.policyXMLSasToken != null) { TemplateParameterProperties policyTemplateSasTokenProperties = new TemplateParameterProperties() { value = exc.policyXMLSasToken }; parameters.Add(ParameterNames.PolicyXMLSasToken, policyTemplateSasTokenProperties); } } if (exc.paramServiceUrl) { Dictionary <string, string> serviceUrls = new Dictionary <string, string>(); APIExtractor apiExc = new APIExtractor(new FileWriter()); foreach (string apiName in apisToExtract) { string validApiName = ExtractorUtils.GenValidParamName(apiName, ParameterPrefix.Api); string serviceUrl = exc.serviceUrlParameters != null?GetApiServiceUrlFromParameters(apiName, exc.serviceUrlParameters) : await apiExc.GetAPIServiceUrl(exc.sourceApimName, exc.resourceGroup, apiName); serviceUrls.Add(validApiName, serviceUrl); } TemplateObjectParameterProperties serviceUrlProperties = new TemplateObjectParameterProperties() { value = serviceUrls }; parameters.Add(ParameterNames.ServiceUrl, serviceUrlProperties); } if (exc.paramNamedValue) { Dictionary <string, string> namedValues = new Dictionary <string, string>(); PropertyExtractor pExc = new PropertyExtractor(); string[] properties = await pExc.GetPropertiesAsync(exc.sourceApimName, exc.resourceGroup); foreach (var extractedProperty in properties) { JToken oProperty = JObject.Parse(extractedProperty); string propertyName = ((JValue)oProperty["name"]).Value.ToString(); string fullPropertyResource = await pExc.GetPropertyDetailsAsync(exc.sourceApimName, exc.resourceGroup, propertyName); PropertyTemplateResource propertyTemplateResource = JsonConvert.DeserializeObject <PropertyTemplateResource>(fullPropertyResource); string propertyValue = propertyTemplateResource.properties.value; string validPName = ExtractorUtils.GenValidParamName(propertyName, ParameterPrefix.Property); namedValues.Add(validPName, propertyValue); } TemplateObjectParameterProperties namedValueProperties = new TemplateObjectParameterProperties() { value = namedValues }; parameters.Add(ParameterNames.NamedValues, namedValueProperties); } if (exc.paramApiLoggerId) { TemplateObjectParameterProperties loggerIdProperties = new TemplateObjectParameterProperties() { value = apiLoggerId }; parameters.Add(ParameterNames.ApiLoggerId, loggerIdProperties); } if (exc.paramLogResourceId) { TemplateObjectParameterProperties loggerResourceIdProperties = new TemplateObjectParameterProperties() { value = loggerResourceIds }; parameters.Add(ParameterNames.LoggerResourceId, loggerResourceIdProperties); } masterTemplate.parameters = parameters; return(masterTemplate); }
/// <summary> /// Generate the ARM assets for the backend resources /// </summary> /// <param name="apimname"></param> /// <param name="resourceGroup"></param> /// <param name="singleApiName"></param> /// <param name="apiTemplateResources"></param> /// <param name="propertyResources"></param> /// <param name="policyXMLBaseUrl"></param> /// <param name="policyXMLSasToken"></param> /// <param name="extractBackendParameters"></param> /// <returns>a combination of a Template and the value for the BackendSettings parameter</returns> public async Task <Tuple <Template, Dictionary <string, BackendApiParameters> > > GenerateBackendsARMTemplateAsync(string apimname, string resourceGroup, string singleApiName, List <TemplateResource> apiTemplateResources, List <TemplateResource> propertyResources, Extractor exc) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting backends from service"); Template armTemplate = GenerateEmptyPropertyTemplateWithParameters(); if (exc.paramBackend) { TemplateParameterProperties extractBackendParametersProperties = new TemplateParameterProperties() { type = "object" }; armTemplate.parameters.Add(ParameterNames.BackendSettings, extractBackendParametersProperties); } List <TemplateResource> templateResources = new List <TemplateResource>(); // isolate api and operation policy resources in the case of a single api extraction, as they may reference backends var policyResources = apiTemplateResources.Where(resource => (resource.type == ResourceTypeConstants.APIPolicy || resource.type == ResourceTypeConstants.APIOperationPolicy || resource.type == ResourceTypeConstants.ProductPolicy)); var namedValueResources = propertyResources.Where(resource => (resource.type == ResourceTypeConstants.Property)); // pull all backends for service JObject oBackends = new JObject(); var oBackendParameters = new Dictionary <string, BackendApiParameters>(); int skipNumberOfBackends = 0; do { string backends = await GetBackendsAsync(apimname, resourceGroup, skipNumberOfBackends); oBackends = JObject.Parse(backends); foreach (var item in oBackends["value"]) { string backendName = ((JValue)item["name"]).Value.ToString(); string backend = await GetBackendDetailsAsync(apimname, resourceGroup, backendName); // convert returned backend to template resource class BackendTemplateResource backendTemplateResource = JsonConvert.DeserializeObject <BackendTemplateResource>(backend); backendTemplateResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backendName}')]"; backendTemplateResource.apiVersion = GlobalConstants.APIVersion; bool includeBackend = false; ////only extract the backend if this is a full extraction, or in the case of a single api, if it is referenced by one of the policies if (singleApiName == null) { // if the user is extracting all apis, extract all the backends includeBackend = true; } else { // check extracted policies to see if the backend is referenced. foreach (PolicyTemplateResource policyTemplateResource in policyResources) { string policyContent = ExtractorUtils.GetPolicyContent(exc, policyTemplateResource); if (DoesPolicyReferenceBackend(policyContent, namedValueResources, backendName, backendTemplateResource)) { // backend was used in policy, extract it includeBackend = true; // dont need to go through all policies if the back end has already been found break; } } } if (includeBackend) { if (exc.paramBackend) { var apiToken = new BackendApiParameters(); string validApiParamName = ExtractorUtils.GenValidParamName(backendName, ParameterPrefix.Diagnostic).ToLower(); if (!string.IsNullOrEmpty(backendTemplateResource.properties.resourceId)) { apiToken.resourceId = backendTemplateResource.properties.resourceId; backendTemplateResource.properties.resourceId = $"[parameters('{ParameterNames.BackendSettings}').{validApiParamName}.resourceId]"; } if (!string.IsNullOrEmpty(backendTemplateResource.properties.url)) { apiToken.url = backendTemplateResource.properties.url; backendTemplateResource.properties.url = $"[parameters('{ParameterNames.BackendSettings}').{validApiParamName}.url]"; } if (!string.IsNullOrEmpty(backendTemplateResource.properties.protocol)) { apiToken.protocol = backendTemplateResource.properties.protocol; backendTemplateResource.properties.protocol = $"[parameters('{ParameterNames.BackendSettings}').{validApiParamName}.protocol]"; } oBackendParameters.Add(validApiParamName, apiToken); } Console.WriteLine("'{0}' Backend found", backendName); templateResources.Add(backendTemplateResource); } } skipNumberOfBackends += GlobalConstants.NumOfRecords; }while (oBackends["nextLink"] != null); armTemplate.resources = templateResources.ToArray(); return(new Tuple <Template, Dictionary <string, BackendApiParameters> >(armTemplate, oBackendParameters)); }
public async Task <Template> GenerateNamedValuesTemplateAsync(string singleApiName, List <TemplateResource> apiTemplateResources, Extractor exc, BackendExtractor backendExtractor, List <TemplateResource> loggerTemplateResources) { Template armTemplate = GenerateEmptyPropertyTemplateWithParameters(); if (exc.paramNamedValue) { TemplateParameterProperties namedValueParameterProperties = new TemplateParameterProperties() { type = "object" }; armTemplate.parameters.Add(ParameterNames.NamedValues, namedValueParameterProperties); } if (exc.paramNamedValuesKeyVaultSecrets) { TemplateParameterProperties keyVaultNamedValueParameterProperties = new TemplateParameterProperties() { type = "object" }; armTemplate.parameters.Add(ParameterNames.NamedValueKeyVaultSecrets, keyVaultNamedValueParameterProperties); } if (exc.notIncludeNamedValue == true) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Skipping extracting named values from service"); return(armTemplate); } Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting named values from service"); List <TemplateResource> templateResources = new List <TemplateResource>(); // pull all named values (properties) for service string[] properties = await GetPropertiesAsync(exc.sourceApimName, exc.resourceGroup); // isolate api and operation policy resources in the case of a single api extraction, as they may reference named value var policyResources = apiTemplateResources.Where(resource => (resource.type == ResourceTypeConstants.APIPolicy || resource.type == ResourceTypeConstants.APIOperationPolicy || resource.type == ResourceTypeConstants.ProductPolicy)); foreach (var extractedProperty in properties) { JToken oProperty = JObject.Parse(extractedProperty); string propertyName = ((JValue)oProperty["name"]).Value.ToString(); string fullPropertyResource = await GetPropertyDetailsAsync(exc.sourceApimName, exc.resourceGroup, propertyName); // convert returned named value to template resource class PropertyTemplateResource propertyTemplateResource = JsonConvert.DeserializeObject <PropertyTemplateResource>(fullPropertyResource); propertyTemplateResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{propertyName}')]"; propertyTemplateResource.type = ResourceTypeConstants.Property; propertyTemplateResource.apiVersion = GlobalConstants.APIVersion; propertyTemplateResource.scale = null; if (exc.paramNamedValue) { propertyTemplateResource.properties.value = $"[parameters('{ParameterNames.NamedValues}').{ExtractorUtils.GenValidParamName(propertyName, ParameterPrefix.Property)}]"; } //Hide the value field if it is a keyvault named value if (propertyTemplateResource.properties.keyVault != null) { propertyTemplateResource.properties.value = null; } if (propertyTemplateResource.properties.keyVault != null && exc.paramNamedValuesKeyVaultSecrets) { propertyTemplateResource.properties.keyVault.secretIdentifier = $"[parameters('{ParameterNames.NamedValueKeyVaultSecrets}').{ExtractorUtils.GenValidParamName(propertyName, ParameterPrefix.Property)}]"; } if (singleApiName == null) { // if the user is executing a full extraction, extract all the loggers Console.WriteLine("'{0}' Named value found", propertyName); templateResources.Add(propertyTemplateResource); } else { // if the user is executing a single api, extract all the named values used in the template resources bool foundInPolicy = DoesPolicyReferenceNamedValue(exc, policyResources, propertyName, propertyTemplateResource); bool foundInBackEnd = await backendExtractor.IsNamedValueUsedInBackends(exc.sourceApimName, exc.resourceGroup, singleApiName, apiTemplateResources, exc, propertyName, propertyTemplateResource.properties.displayName); bool foundInLogger = DoesLoggerReferenceNamedValue(loggerTemplateResources, propertyName, propertyTemplateResource); // check if named value is referenced in a backend if (foundInPolicy || foundInBackEnd || foundInLogger) { // named value was used in policy, extract it Console.WriteLine("'{0}' Named value found", propertyName); templateResources.Add(propertyTemplateResource); } } } armTemplate.resources = templateResources.ToArray(); return(armTemplate); }