/// <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, ExtractorParameters extractorParameters) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting backends from service"); Template armTemplate = this.templateBuilder.GenerateTemplateWithApimServiceNameProperty().Build(); if (extractorParameters.ParameterizeBackend) { 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 this.GetBackendsAsync(apimname, resourceGroup, skipNumberOfBackends); oBackends = JObject.Parse(backends); foreach (var item in oBackends["value"]) { string backendName = ((JValue)item["name"]).Value.ToString(); string backend = await this.GetBackendDetailsAsync(apimname, resourceGroup, backendName); // convert returned backend to template resource class BackendTemplateResource backendTemplateResource = backend.Deserialize <BackendTemplateResource>(); 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 = PolicyTemplateUtils.GetPolicyContent(extractorParameters, policyTemplateResource); if (this.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 (extractorParameters.ParameterizeBackend) { var apiToken = new BackendApiParameters(); string validApiParamName = ParameterNamingHelper.GenerateValidParameterName(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)); }
/// <summary> /// Generate the ARM assets for the backend resources /// </summary> /// <returns>a combination of a Template and the value for the BackendSettings parameter</returns> public async Task <Template <BackendTemplateResources> > GenerateBackendsTemplateAsync( string singleApiName, List <PolicyTemplateResource> apiPolicies, List <NamedValueTemplateResource> namedValues, string baseFilesGenerationDirectory, ExtractorParameters extractorParameters) { var backendTemplate = this.templateBuilder .GenerateTemplateWithApimServiceNameProperty() .AddParameterizeBackendProperty(extractorParameters) .Build <BackendTemplateResources>(); var backends = await this.backendClient.GetAllAsync(extractorParameters); if (backends.IsNullOrEmpty()) { this.logger.LogWarning("No backends found for apim instance '{0}'", extractorParameters.SourceApimName); return(backendTemplate); } foreach (var backendResource in backends) { var originalBackendName = backendResource.Name; backendResource.Name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{originalBackendName}')]"; backendResource.Type = ResourceTypeConstants.Backend; backendResource.ApiVersion = GlobalConstants.ApiVersion; if (string.IsNullOrEmpty(singleApiName)) { // if the user is extracting all apis, extract all the backends backendTemplate.TypedResources.Backends.Add(backendResource); SaveBackendApiParametersToCache(); } else { if (apiPolicies.IsNullOrEmpty()) { continue; } foreach (var policyTemplateResource in apiPolicies) { var policyContent = this.policyExtractor.GetCachedPolicyContent(policyTemplateResource, baseFilesGenerationDirectory); if (this.DoesPolicyReferenceBackend(policyContent, namedValues, originalBackendName, backendResource)) { // backend was used in policy, extract it backendTemplate.TypedResources.Backends.Add(backendResource); SaveBackendApiParametersToCache(); // don't need to go through all policies if the back end has already been found break; } } } void SaveBackendApiParametersToCache() { if (!extractorParameters.ParameterizeBackend) { this.logger.LogDebug("Parameter '{0}' is false. Skipping storing api-backend mapping in cache", nameof(ExtractorParameters.ParameterizeBackend)); return; } var backendApiParameters = new BackendApiParameters(); var backendValidName = ParameterNamingHelper.GenerateValidParameterName(originalBackendName, ParameterPrefix.Diagnostic).ToLower(); if (!string.IsNullOrEmpty(backendResource.Properties.ResourceId)) { backendApiParameters.ResourceId = backendResource.Properties.ResourceId; backendResource.Properties.ResourceId = $"[parameters('{ParameterNames.BackendSettings}').{backendValidName}.resourceId]"; } if (!string.IsNullOrEmpty(backendResource.Properties.Url)) { backendApiParameters.Url = backendResource.Properties.Url; backendResource.Properties.Url = $"[parameters('{ParameterNames.BackendSettings}').{backendValidName}.url]"; } if (!string.IsNullOrEmpty(backendResource.Properties.Protocol)) { backendApiParameters.Protocol = backendResource.Properties.Protocol; backendResource.Properties.Protocol = $"[parameters('{ParameterNames.BackendSettings}').{backendValidName}.protocol]"; } if (!backendTemplate.TypedResources.BackendNameParametersCache.ContainsKey(backendValidName)) { backendTemplate.TypedResources.BackendNameParametersCache.Add(backendValidName, backendApiParameters); } } } return(backendTemplate); }