Exemple #1
0
        private async Task AssignApisToProducts(DeploymentTemplate template)
        {
            var products = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/products");

            foreach (JObject productObject in (products == null ? new JArray() : products.Value <JArray>("value")))
            {
                var id = productObject.Value <string>("id");
                var productInstance = await resourceCollector.GetResource(id);

                var productApis = await resourceCollector.GetResource(id + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

                // Skip product if not related to an API in the filter.
                if (productApis != null && productApis.Value <JArray>("value").Count > 0)
                {
                    foreach (JObject productApi in (productApis == null ? new JArray() : productApis.Value <JArray>("value")))
                    {
                        var productProperties = productApi["properties"];
                        if (productProperties["apiVersionSetId"] != null)
                        {
                            var apiVersionSetId = new AzureResourceId(productProperties["apiVersionSetId"].ToString()).ValueAfter("api-version-sets");
                            productProperties["apiVersionSetId"] = $"[resourceId('Microsoft.ApiManagement/service/api-version-sets', parameters('{GetServiceName(servicename)}'), '{apiVersionSetId}')]";
                        }

                        template.resources.Add(template.AddProductApi(productApi));
                    }
                }
            }
        }
        public void PolicyHandeBackendUrl(JObject policy, string apiname, DeploymentTemplate template)
        {
            var policyPropertyName = policy["properties"].Value <string>("policyContent") == null ? "value" : "policyContent";
            var policyContent      = policy["properties"].Value <string>(policyPropertyName);

            var policyXMLDoc = XDocument.Parse(policyContent);
            //find the last backend service and add as parameter
            var backendService = policyXMLDoc.Descendants().Where(dd => dd.Name == "set-backend-service").LastOrDefault();

            if (backendService != null)
            {
                // This does not work in all cases. If you want to be sure, use a property as placeholder.
                if (backendService.Attribute("base-url") != null && !backendService.Attribute("base-url").Value.Contains("{{") && !parametrizePropertiesOnly)
                {
                    string baseUrl   = backendService.Attribute("base-url").Value;
                    var    paramname = template.AddParameter($"api_{apiname}_backendurl", "string", baseUrl);
                    if (replaceSetBackendServiceBaseUrlAsProperty)
                    {
                        policy["properties"][policyPropertyName] = CreatePolicyContentReplaceBaseUrlWithProperty(backendService, policyContent, paramname);

                        string          id         = GetIdFromPolicy(policy);
                        AzureResourceId resourceId = new AzureResourceId(id);
                        var             lookFor    = $"/service/{resourceId.ValueAfter("service")}";
                        var             index      = id.IndexOf(lookFor);
                        var             serviceId  = id.Substring(0, index + lookFor.Length);
                        var             property   = new
                        {
                            id         = $"{serviceId}/properties/{paramname}",
                            type       = "Microsoft.ApiManagement/service/namedValues",
                            name       = paramname,
                            properties = new
                            {
                                displayName = paramname,
                                value       = $"[parameters('{paramname}')]",
                                secret      = false
                            }
                        };
                        template.AddNamedValues(JObject.FromObject(property));
                    }
                    else
                    {
                        policy["properties"][policyPropertyName] = CreatePolicyContentReplaceBaseUrl(backendService, policyContent, $"parameters('{paramname}')");
                    }
                }
            }
        }
Exemple #3
0
        private async Task AddVersionSet(JObject apiTemplateResource, JObject apiInstance, DeploymentTemplate template)
        {
            string apiversionsetid = apiTemplateResource["properties"].Value <string>("apiVersionSetId");

            if (!string.IsNullOrEmpty(apiversionsetid))
            {
                AzureResourceId aiapiversion = new AzureResourceId(apiInstance["properties"].Value <string>("apiVersionSetId"));

                var versionsetResource = template.AddVersionSet(await resourceCollector.GetResource(apiversionsetid));
                if (versionsetResource != null)
                {
                    string resourceid = $"[resourceId('Microsoft.ApiManagement/service/api-version-sets',{versionsetResource.GetResourceId()})]";
                    apiTemplateResource["properties"]["apiVersionSetId"] = resourceid;
                    apiTemplateResource.Value <JArray>("dependsOn").Add(resourceid);
                }
            }
        }
        public async Task <JObject> GenerateTemplate()
        {
            DeploymentTemplate template = new DeploymentTemplate(this.parametrizePropertiesOnly, this.fixedServiceNameParameter, this.createApplicationInsightsInstance, this.parameterizeBackendFunctionKey, this.separatePolicyOutputFolder, this.chainDependencies);

            if (exportPIManagementInstance)
            {
                var apim = await resourceCollector.GetResource(GetAPIMResourceIDString());

                var apimTemplateResource = template.AddAPIManagementInstance(apim);
                await AddServiceResource(apimTemplateResource, "/policies", policy =>
                {
                    PolicyHandleProperties(policy, "Global", "Global");
                    return(template.CreatePolicy(policy));
                });
                await AddServiceResource(apimTemplateResource, "/identityProviders",
                                         identityProvider => template.CreateIdentityProvider(identityProvider, false));

                var loggers = await AddServiceResource(apimTemplateResource, "/loggers", logger =>
                {
                    bool isApplicationInsightsLogger = (logger["properties"]?["loggerType"]?.Value <string>() ?? string.Empty) == "applicationInsights";
                    if (createApplicationInsightsInstance && isApplicationInsightsLogger)
                    {
                        apimTemplateResource.Value <JArray>("resources").Add(template.AddApplicationInsightsInstance(logger));
                    }
                    if (!createApplicationInsightsInstance || !isApplicationInsightsLogger)
                    {
                        HandleProperties(logger.Value <string>("name"), "Logger", logger["properties"].ToString());
                    }
                    return(template.CreateLogger(logger, false));
                });
                await AddServiceResource(apimTemplateResource, "/diagnostics",
                                         diagnostic => template.CreateDiagnostic(diagnostic, loggers == null ? new JArray() : loggers.Value <JArray>("value"), false));

                if (this.exportTags)
                {
                    await AddServiceResource(apimTemplateResource, "/tags",
                                             tags => template.CreateTags(tags, false));
                }
            }
            //check for special productname filter
            var getProductname = Regex.Match(apiFilters, "(?<=productname\\s*eq\\s*\\')(.+?)(?=\\')", RegexOptions.IgnoreCase);

            if (getProductname.Success)
            {
                apiFilters = Regex.Replace(apiFilters, "productname\\s*eq\\s*\'(.+?)(\')", "");

                var apiFilterList = new List <string>();
                var productApis   = await resourceCollector.GetResource(GetAPIMResourceIDString() + $"/products/{getProductname.Value}/apis");

                foreach (JObject api in productApis["value"])
                {
                    apiFilterList.Add($"name eq '{api["name"]}'");
                }

                apiFilters = "(" + string.Join(" or ", apiFilterList) + ")" + apiFilters;
            }


            var apiObjectResult = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

            IEnumerable <JToken> apis = new List <JToken>();

            if (apiObjectResult != null)
            {
                apis = (!string.IsNullOrEmpty(apiVersion) ? apiObjectResult.Value <JArray>("value").Where(aa => aa["properties"].Value <string>("apiVersion") == this.apiVersion) : apiObjectResult.Value <JArray>("value"));
                foreach (JObject apiObject in apis)
                {
                    var id = apiObject.Value <string>("id");


                    var apiInstance = await resourceCollector.GetResource(id);

                    var apiTemplateResource = template.AddApi(apiInstance);

                    //Api version set
                    string apiversionsetid = apiTemplateResource["properties"].Value <string>("apiVersionSetId");
                    if (!string.IsNullOrEmpty(apiversionsetid))
                    {
                        AzureResourceId aiapiversion = new AzureResourceId(apiInstance["properties"].Value <string>("apiVersionSetId"));

                        var versionsetResource = template.AddVersionSet(await resourceCollector.GetResource(apiversionsetid));
                        if (versionsetResource != null)
                        {
                            string resourceid = $"[resourceId('Microsoft.ApiManagement/service/apiVersionSets',{versionsetResource.GetResourceId()})]";
                            apiTemplateResource["properties"]["apiVersionSetId"] = resourceid;
                            apiTemplateResource.Value <JArray>("dependsOn").Add(resourceid);
                        }
                    }
                    string openidProviderId = GetOpenIdProviderId(apiTemplateResource);
                    if (!String.IsNullOrWhiteSpace(openidProviderId))
                    {
                        if (this.openidConnectProviders == null)
                        {
                            openidConnectProviders = new List <JObject>();
                            var providers = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/openidConnectProviders");

                            foreach (JObject openidConnectProvider in (providers == null ? new JArray() : providers.Value <JArray>("value")))
                            {
                                openidConnectProviders.Add(openidConnectProvider);
                            }
                        }
                        var openIdProvider = this.openidConnectProviders.FirstOrDefault(x => x.Value <string>("name") == openidProviderId);
                        template.CreateOpenIDConnectProvider(openIdProvider, true);
                    }

                    var operations = await resourceCollector.GetResource(id + "/operations");

                    string previousOperationName = null;
                    foreach (JObject operation in (operations == null
                        ? new JArray()
                        : operations.Value <JArray>("value")))
                    {
                        var opId = operation.Value <string>("id");

                        var operationInstance = await resourceCollector.GetResource(opId);

                        var operationTemplateResource = template.CreateOperation(operationInstance);
                        if (!exportSwaggerDefinition)
                        {
                            apiTemplateResource.Value <JArray>("resources").Add(operationTemplateResource);
                        }
                        var operationPolicies = await resourceCollector.GetResource(opId + "/policies");

                        foreach (JObject policy in (operationPolicies == null
                            ? new JArray()
                            : operationPolicies.Value <JArray>("value")))
                        {
                            var pol = template.CreatePolicy(policy);

                            //add properties
                            this.PolicyHandleProperties(pol, apiTemplateResource.Value <string>("name"),
                                                        GetOperationName(operationInstance));

                            var operationSuffix = apiInstance.Value <string>("name") + "_" +
                                                  operationInstance.Value <string>("name");
                            //Handle Azure Resources
                            if (!this.PolicyHandeAzureResources(pol, apiTemplateResource.Value <string>("name"),
                                                                template))
                            {
                                PolicyHandeBackendUrl(pol, operationSuffix, template);
                            }

                            var    policyPropertyName = policy["properties"].Value <string>("policyContent") == null ? "value" : "policyContent";
                            string policyContent      = policy["properties"].Value <string>(policyPropertyName);

                            var backendid = TemplateHelper.GetBackendIdFromnPolicy(policyContent);

                            if (!string.IsNullOrEmpty(backendid))
                            {
                                BackendObject bo = await HandleBackend(template, operationSuffix, backendid);

                                JObject backendInstance = bo?.backendInstance;
                                if (backendInstance != null)
                                {
                                    if (apiTemplateResource.Value <JArray>("dependsOn") == null)
                                    {
                                        apiTemplateResource["dependsOn"] = new JArray();
                                    }

                                    //add dependeOn
                                    apiTemplateResource.Value <JArray>("dependsOn").Add(
                                        $"[resourceId('Microsoft.ApiManagement/service/backends', parameters('{GetServiceName(servicename)}'), '{backendInstance.Value<string>("name")}')]");
                                }
                                if (bo?.backendProperty != null)
                                {
                                    if (bo.backendProperty.type == Property.PropertyType.LogicApp)
                                    {
                                        var urltemplatestring = TemplateHelper.GetAPIMGenereatedRewritePolicyTemplate(policyContent);
                                        var match             = Regex.Match(urltemplatestring, "{{(?<name>[-_.a-zA-Z0-9]*)}}");
                                        if (match.Success)
                                        {
                                            string name = match.Groups["name"].Value;
                                            var    idp  = identifiedProperties.Where(pp => pp.name == name).FirstOrDefault();
                                            if (idp != null)
                                            {
                                                idp.extraInfo = bo.backendProperty.extraInfo;
                                                idp.type      = Property.PropertyType.LogicAppRevisionGa;
                                            }
                                        }
                                    }
                                }
                            }
                            if (exportCertificates)
                            {
                                await AddCertificate(policy, template);
                            }

                            if (Directory.Exists(separatePolicyOutputFolder))
                            {
                                pol = ReplacePolicyWithFileLink(template, pol, operationSuffix);
                            }

                            if (exportSwaggerDefinition)
                            {
                                apiTemplateResource.Value <JArray>("resources").Add(pol);
                            }
                            else
                            {
                                operationTemplateResource.Value <JArray>("resources").Add(pol);
                            }

                            //all other fixed let's add the not found properties


                            //handle nextlink?
                        }
                        //handle nextlink?

                        //add dependency to make sure not all operations are deployed at the same time. This results in timeouts when having a lot of operations
                        if (previousOperationName != null)
                        {
                            //operationTemplateResource.Value<JArray>("dependsOn").Where(aa => aa.ToString().Contains("'Microsoft.ApiManagement/service/apis'")).First();
                            string apiname = parametrizePropertiesOnly ? $"'{apiInstance.Value<string>("name")}'" : $"parameters('api_{apiInstance.Value<string>("name")}_name')";
                            var    dep     = $"[resourceId('Microsoft.ApiManagement/service/apis/operations', parameters('{GetServiceName(servicename)}'), {apiname}, '{previousOperationName}')]";
                            operationTemplateResource.Value <JArray>("dependsOn").Add(dep);
                        }
                        previousOperationName = operationInstance.Value <string>("name");
                    }
                    if (exportSwaggerDefinition)
                    {
                        apiTemplateResource["properties"]["contentFormat"] = "swagger-json";
                        var swaggerExport = await resourceCollector.GetResource(id + "?format=swagger-link&export=true", apiversion: "2019-01-01");

                        var swaggerUrl     = swaggerExport.Value <string>("link");
                        var swaggerContent = await resourceCollector.GetResourceByURL(swaggerUrl);

                        var serviceUrl = apiInstance["properties"].Value <string>("serviceUrl");
                        if (!String.IsNullOrWhiteSpace(serviceUrl))
                        {
                            var serviceUri = new Uri(serviceUrl);
                            swaggerContent["host"]     = serviceUri.Host;
                            swaggerContent["basePath"] = serviceUri.AbsolutePath;
                            swaggerContent["schemes"]  = JArray.FromObject(new[] { serviceUri.Scheme });
                        }
                        apiTemplateResource["properties"]["contentValue"] = swaggerContent.ToString();
                    }

                    var apiPolicies = await resourceCollector.GetResource(id + "/policies");

                    foreach (JObject policy in (apiPolicies == null ? new JArray() : apiPolicies.Value <JArray>("value")))
                    {
                        //Handle SOAP Backend
                        var policyPropertyName = policy["properties"].Value <string>("policyContent") == null ? "value" : "policyContent";
                        var backendid          = TemplateHelper.GetBackendIdFromnPolicy(policy["properties"].Value <string>(policyPropertyName));

                        if (exportCertificates)
                        {
                            await AddCertificate(policy, template);
                        }
                        PolicyHandeBackendUrl(policy, apiInstance.Value <string>("name"), template);
                        var policyTemplateResource = template.CreatePolicy(policy);
                        this.PolicyHandleProperties(policy, apiTemplateResource.Value <string>("name"), null);
                        apiTemplateResource.Value <JArray>("resources").Add(policyTemplateResource);


                        if (!string.IsNullOrEmpty(backendid))
                        {
                            var bo = await HandleBackend(template, apiObject.Value <string>("name"), backendid);

                            JObject backendInstance = bo.backendInstance;
                            if (backendInstance == null)
                            {
                                if (apiTemplateResource.Value <JArray>("dependsOn") == null)
                                {
                                    apiTemplateResource["dependsOn"] = new JArray();
                                }

                                //add dependeOn
                                apiTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/backends', parameters('{GetServiceName(servicename)}'), '{backendInstance.Value<string>("name")}')]");
                            }
                        }

                        if (Directory.Exists(separatePolicyOutputFolder))
                        {
                            ReplacePolicyWithFileLink(template, policyTemplateResource, apiInstance.Value <string>("name") + "_AllOperations");
                        }

                        //handle nextlink?
                    }

                    if (!exportSwaggerDefinition)
                    {
                        var apiSchemas = await resourceCollector.GetResource(id + "/schemas");

                        foreach (JObject schema in (apiSchemas == null ? new JArray() : apiSchemas.Value <JArray>("value")))
                        {
                            var schemaTemplate = template.CreateAPISchema(schema);
                            apiTemplateResource.Value <JArray>("resources").Add(JObject.FromObject(schemaTemplate));
                        }
                    }

                    //diagnostics
                    var loggers     = resourceCollector.GetResource(GetAPIMResourceIDString() + "/loggers").Result;
                    var logger      = loggers == null ? new JArray() : loggers.Value <JArray>("value");
                    var diagnostics = await resourceCollector.GetResource(id + "/diagnostics", apiversion : "2019-01-01");

                    foreach (JObject diagnostic in diagnostics.Value <JArray>("value"))
                    {
                        if (diagnostic.Value <string>("type") == "Microsoft.ApiManagement/service/apis/diagnostics")
                        {
                            var diagnosticTemplateResource = template.CreateApiDiagnostic(diagnostic, logger, false);
                            apiTemplateResource.Value <JArray>("resources").Add(diagnosticTemplateResource);
                        }
                    }

                    //tags
                    if (this.exportTags)
                    {
                        var apiTags = await resourceCollector.GetResource(id + "/tags");

                        foreach (JObject tag in (apiTags == null ? new JArray() : apiTags.Value <JArray>("value")))
                        {
                            var tagTemplate = template.CreateAPITag(tag);
                            apiTemplateResource.Value <JArray>("resources").Add(JObject.FromObject(tagTemplate));
                            //shoudl we get the root tag instead of copying underlaying tags?
                            if (!exportPIManagementInstance)
                            {
                                tagTemplate.RemoveNameAt(1);
                                tagTemplate.type = "Microsoft.ApiManagement/service/tags";
                                tagTemplate.dependsOn.RemoveAll();
                                template.resources.Add(JObject.FromObject(tagTemplate));
                                apiTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/tags', {tagTemplate.GetResourceId()})]");
                            }
                        }
                    }

                    //handle nextlink?
                }
            }

            // Export all groups if we don't export the products.
            if (exportGroups && !exportProducts)
            {
                var groups = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/groups");

                foreach (JObject groupObject in (groups == null ? new JArray() : groups.Value <JArray>("value")))
                {
                    //cannot edit och create built in groups
                    if (groupObject["properties"].Value <bool>("builtIn") == false)
                    {
                        template.AddGroup(groupObject);
                    }
                }
            }

            if (exportProducts)
            {
                var products = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/products");

                foreach (JObject productObject in (products == null ? new JArray() : products.Value <JArray>("value")))
                {
                    var id          = productObject.Value <string>("id");
                    var productApis = await resourceCollector.GetResource(id + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

                    // Skip product if not related to an API in the filter.
                    if (productApis != null && productApis.Value <JArray>("value").Count > 0)
                    {
                        //skip product when filter by productname and not this product
                        if (getProductname.Success && !getProductname.Value.Equals(productObject.Value <string>("name"), StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        var productTemplateResource = template.AddProduct(productObject);

                        var listOfApiNamesInThisSearch = apis.Select(api => api.Value <string>("name")).ToList();

                        foreach (JObject productApi in (productApis == null ? new JArray() : productApis.Value <JArray>("value")))
                        {
                            //only take the api's inside the api query
                            if (!listOfApiNamesInThisSearch.Contains(productApi.Value <string>("name")))
                            {
                                continue;
                            }

                            var productProperties = productApi["properties"];
                            if (productProperties["apiVersionSetId"] != null)
                            {
                                var apiVersionSetId = new AzureResourceId(productProperties["apiVersionSetId"].ToString()).ValueAfter("apiVersionSets");
                                productProperties["apiVersionSetId"] = $"[resourceId('Microsoft.ApiManagement/service/apiVersionSets', parameters('{GetServiceName(servicename)}'), '{apiVersionSetId}')]";
                            }
                            productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(productApi));

                            //also add depends On for API
                            string apiname = parametrizePropertiesOnly ? $"'{productApi.Value<string>("name")}'" : $"parameters('api_{productApi.Value<string>("name")}_name')";
                            productTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{GetServiceName(servicename)}'), {apiname})]");
                        }

                        if (exportGroups)
                        {
                            var groups = await resourceCollector.GetResource(id + "/groups");

                            foreach (JObject group in (groups == null ? new JArray() : groups.Value <JArray>("value")))
                            {
                                if (group["properties"].Value <bool>("builtIn") == false)
                                {
                                    // Add group resource
                                    var groupObject = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/groups/" + group.Value <string>("name"));

                                    template.AddGroup(groupObject);
                                    productTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/groups', parameters('{GetServiceName(servicename)}'), parameters('{template.AddParameter($"group_{group.Value<string>("name")}_name", "string", group.Value<string>("name"))}'))]");
                                }
                                productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(group));
                            }
                        }
                        var policies = await resourceCollector.GetResource(id + "/policies");

                        foreach (JObject policy in (policies == null ? new JArray() : policies.Value <JArray>("value")))
                        {
                            productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(policy));
                        }
                    }
                }
            }

            var properties = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/namedValues", apiversion : "2020-06-01-preview");

            //  var properties = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/properties",apiversion: "2020-06-01-preview");
            //has more?
            foreach (JObject propertyObject in (properties == null ? new JArray() : properties.Value <JArray>("value")))
            {
                var id          = propertyObject.Value <string>("id");
                var displayName = propertyObject["properties"].Value <string>("displayName");

                var identifiedProperty = this.identifiedProperties.Where(idp => displayName.EndsWith(idp.name)).FirstOrDefault();
                if (identifiedProperty == null)
                {
                    identifiedProperty = identifiedProperties.FirstOrDefault(idp => displayName == $"{idp.name}-key" && idp.type == Property.PropertyType.Function);
                }
                if (identifiedProperty != null)
                {
                    if (identifiedProperty.type == Property.PropertyType.LogicApp)
                    {
                        propertyObject["properties"]["value"] = $"[concat('sv=',{identifiedProperty.extraInfo}.queries.sv,'&sig=',{identifiedProperty.extraInfo}.queries.sig)]";
                    }
                    else if (identifiedProperty.type == Property.PropertyType.LogicAppRevisionGa)
                    {
                        propertyObject["properties"]["value"] = $"[{identifiedProperty.extraInfo}.queries.sig]";
                    }
                    else if (identifiedProperty.type == Property.PropertyType.Function)
                    {
                        propertyObject["properties"]["value"] = $"[{identifiedProperty.extraInfo}]";
                    }


                    var propertyTemplate = template.AddNamedValues(propertyObject);

                    if (!parametrizePropertiesOnly)
                    {
                        string resourceid = $"[resourceId('Microsoft.ApiManagement/service/namedValues',{propertyTemplate.GetResourceId()})]";
                        foreach (var apiName in identifiedProperty.apis)
                        {
                            var apiTemplate = template.resources.Where(rr => rr.Value <string>("name") == apiName).FirstOrDefault();
                            if (apiTemplate != null)
                            {
                                apiTemplate.Value <JArray>("dependsOn").Add(resourceid);
                            }
                        }
                    }
                }
            }

            return(JObject.FromObject(template));
        }
Exemple #5
0
        public async Task <JObject> GenerateTemplate()
        {
            DeploymentTemplate template = new DeploymentTemplate(this.parametrizePropertiesOnly, this.fixedServiceNameParameter, this.createApplicationInsightsInstance, this.parameterizeBackendFunctionKey);

            if (exportPIManagementInstance)
            {
                var apim = await resourceCollector.GetResource(GetAPIMResourceIDString());

                var apimTemplateResource = template.AddAPIManagementInstance(apim);
                await AddServiceResource(apimTemplateResource, "/policies", policy =>
                {
                    PolicyHandleProperties(policy, "Global", "Global");
                    return(template.CreatePolicy(policy));
                });
                await AddServiceResource(apimTemplateResource, "/identityProviders",
                                         identityProvider => template.CreateIdentityProvider(identityProvider, false));

                var loggers = await AddServiceResource(apimTemplateResource, "/loggers", logger =>
                {
                    bool isApplicationInsightsLogger = (logger["properties"]?["loggerType"]?.Value <string>() ?? string.Empty) == "applicationInsights";
                    if (createApplicationInsightsInstance && isApplicationInsightsLogger)
                    {
                        apimTemplateResource.Value <JArray>("resources").Add(template.AddApplicationInsightsInstance(logger));
                    }
                    if (!createApplicationInsightsInstance || !isApplicationInsightsLogger)
                    {
                        HandleProperties(logger.Value <string>("name"), "Logger", logger["properties"].ToString());
                    }
                    return(template.CreateLogger(logger, false));
                });
                await AddServiceResource(apimTemplateResource, "/diagnostics",
                                         diagnostic => template.CreateDiagnostic(diagnostic, loggers == null ? new JArray() : loggers.Value <JArray>("value"), false));
            }

            var apis = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

            if (apis != null)
            {
                foreach (JObject apiObject in (!string.IsNullOrEmpty(apiVersion) ? apis.Value <JArray>("value").Where(aa => aa["properties"].Value <string>("apiVersion") == this.apiVersion) : apis.Value <JArray>("value")))
                {
                    var id = apiObject.Value <string>("id");


                    var apiInstance = await resourceCollector.GetResource(id);

                    var apiTemplateResource = template.AddApi(apiInstance);

                    //Api version set
                    string apiversionsetid = apiTemplateResource["properties"].Value <string>("apiVersionSetId");
                    if (!string.IsNullOrEmpty(apiversionsetid))
                    {
                        AzureResourceId aiapiversion = new AzureResourceId(apiInstance["properties"].Value <string>("apiVersionSetId"));

                        var versionsetResource = template.AddVersionSet(await resourceCollector.GetResource(apiversionsetid));
                        if (versionsetResource != null)
                        {
                            string resourceid = $"[resourceId('Microsoft.ApiManagement/service/api-version-sets',{versionsetResource.GetResourceId()})]";
                            apiTemplateResource["properties"]["apiVersionSetId"] = resourceid;
                            apiTemplateResource.Value <JArray>("dependsOn").Add(resourceid);
                        }
                    }
                    string openidProviderId = GetOpenIdProviderId(apiTemplateResource);
                    if (!String.IsNullOrWhiteSpace(openidProviderId))
                    {
                        if (this.openidConnectProviders == null)
                        {
                            openidConnectProviders = new List <JObject>();
                            var providers = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/openidConnectProviders");

                            foreach (JObject openidConnectProvider in (providers == null ? new JArray() : providers.Value <JArray>("value")))
                            {
                                openidConnectProviders.Add(openidConnectProvider);
                            }
                        }
                        var openIdProvider = this.openidConnectProviders.FirstOrDefault(x => x.Value <string>("name") == openidProviderId);
                        template.CreateOpenIDConnectProvider(openIdProvider, true);
                    }

                    var operations = await resourceCollector.GetResource(id + "/operations");

                    foreach (JObject operation in (operations == null ? new JArray() : operations.Value <JArray>("value")))
                    {
                        var opId = operation.Value <string>("id");

                        var operationInstance = await resourceCollector.GetResource(opId);

                        var operationTemplateResource = template.CreateOperation(operationInstance);
                        apiTemplateResource.Value <JArray>("resources").Add(operationTemplateResource);


                        var operationPolicies = await resourceCollector.GetResource(opId + "/policies");

                        foreach (JObject policy in (operationPolicies == null ? new JArray() : operationPolicies.Value <JArray>("value")))
                        {
                            var pol = template.CreatePolicy(policy);

                            //add properties
                            this.PolicyHandleProperties(pol, apiTemplateResource.Value <string>("name"), (operationInstance.Value <string>("name").StartsWith("api-") ? operationInstance.Value <string>("name").Substring(4, (operationInstance.Value <string>("name").LastIndexOf("-" + operationInstance["properties"].Value <string>("method").ToLower())) - 4) : operationInstance.Value <string>("name")));

                            var operationSuffix = apiInstance.Value <string>("name") + "_" + operationInstance.Value <string>("name");
                            //Handle Azure Resources
                            if (!this.PolicyHandeAzureResources(pol, apiTemplateResource.Value <string>("name"), template))
                            {
                                PolicyHandeBackendUrl(pol, operationSuffix, template);
                            }

                            var backendid = TemplateHelper.GetBackendIdFromnPolicy(policy["properties"].Value <string>("policyContent"));

                            if (!string.IsNullOrEmpty(backendid))
                            {
                                JObject backendInstance = await HandleBackend(template, operationSuffix, backendid);

                                if (apiTemplateResource.Value <JArray>("dependsOn") == null)
                                {
                                    apiTemplateResource["dependsOn"] = new JArray();
                                }

                                //add dependeOn
                                apiTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/backends', parameters('{GetServiceName(servicename)}'), '{backendInstance.Value<string>("name")}')]");
                            }
                            await AddCertificate(policy, template);

                            operationTemplateResource.Value <JArray>("resources").Add(pol);
                            //handle nextlink?
                        }
                        //handle nextlink?
                    }

                    var apiPolicies = await resourceCollector.GetResource(id + "/policies");

                    foreach (JObject policy in (apiPolicies == null ? new JArray() : apiPolicies.Value <JArray>("value")))
                    {
                        //Handle SOAP Backend
                        var backendid = TemplateHelper.GetBackendIdFromnPolicy(policy["properties"].Value <string>("policyContent"));
                        await AddCertificate(policy, template);

                        PolicyHandeBackendUrl(policy, apiInstance.Value <string>("name"), template);
                        var policyTemplateResource = template.CreatePolicy(policy);
                        this.PolicyHandleProperties(policy, apiTemplateResource.Value <string>("name"), null);
                        apiTemplateResource.Value <JArray>("resources").Add(policyTemplateResource);


                        if (!string.IsNullOrEmpty(backendid))
                        {
                            JObject backendInstance = await HandleBackend(template, apiObject.Value <string>("name"), backendid);

                            if (apiTemplateResource.Value <JArray>("dependsOn") == null)
                            {
                                apiTemplateResource["dependsOn"] = new JArray();
                            }

                            //add dependeOn
                            apiTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/backends', parameters('{GetServiceName(servicename)}'), '{backendInstance.Value<string>("name")}')]");
                        }

                        //handle nextlink?
                    }
                    //schemas
                    var apiSchemas = await resourceCollector.GetResource(id + "/schemas");

                    foreach (JObject schema in (apiSchemas == null ? new JArray() : apiSchemas.Value <JArray>("value")))
                    {
                        var schemaTemplate = template.CreateAPISchema(schema);
                        apiTemplateResource.Value <JArray>("resources").Add(JObject.FromObject(schemaTemplate));
                    }

                    //handle nextlink?
                }
            }

            // Export all groups if we don't export the products.
            if (exportGroups && !exportProducts)
            {
                var groups = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/groups");

                foreach (JObject groupObject in (groups == null ? new JArray() : groups.Value <JArray>("value")))
                {
                    //cannot edit och create built in groups
                    if (groupObject["properties"].Value <bool>("builtIn") == false)
                    {
                        template.AddGroup(groupObject);
                    }
                }
            }

            if (exportProducts)
            {
                var products = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/products");

                foreach (JObject productObject in (products == null ? new JArray() : products.Value <JArray>("value")))
                {
                    var id          = productObject.Value <string>("id");
                    var productApis = await resourceCollector.GetResource(id + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

                    // Skip product if not related to an API in the filter.
                    if (productApis != null && productApis.Value <JArray>("value").Count > 0)
                    {
                        var productTemplateResource = template.AddProduct(productObject);

                        foreach (JObject productApi in (productApis == null ? new JArray() : productApis.Value <JArray>("value")))
                        {
                            var productProperties = productApi["properties"];
                            if (productProperties["apiVersionSetId"] != null)
                            {
                                var apiVersionSetId = new AzureResourceId(productProperties["apiVersionSetId"].ToString()).ValueAfter("api-version-sets");
                                productProperties["apiVersionSetId"] = $"[resourceId('Microsoft.ApiManagement/service/api-version-sets', parameters('{GetServiceName(servicename)}'), '{apiVersionSetId}')]";
                            }
                            productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(productApi));
                        }

                        var groups = await resourceCollector.GetResource(id + "/groups");

                        foreach (JObject group in (groups == null ? new JArray() : groups.Value <JArray>("value")))
                        {
                            if (group["properties"].Value <bool>("builtIn") == false)
                            {
                                // Add group resource
                                var groupObject = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/groups/" + group.Value <string>("name"));

                                template.AddGroup(groupObject);
                            }
                            productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(group));
                            productTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/groups', parameters('{GetServiceName(servicename)}'), '{group.Value<string>("name")}')]");
                        }
                        var policies = await resourceCollector.GetResource(id + "/policies");

                        foreach (JObject policy in (policies == null ? new JArray() : policies.Value <JArray>("value")))
                        {
                            productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(policy));
                        }
                    }
                }
            }

            var properties = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/properties");

            foreach (JObject propertyObject in (properties == null ? new JArray() : properties.Value <JArray>("value")))
            {
                var id   = propertyObject.Value <string>("id");
                var name = propertyObject["properties"].Value <string>("displayName");

                var identifiedProperty = this.identifiedProperties.Where(idp => name.EndsWith(idp.name)).FirstOrDefault();
                if (identifiedProperty == null)
                {
                    identifiedProperty = identifiedProperties.FirstOrDefault(idp => name == $"{idp.name}-key" && idp.type == Property.PropertyType.Function);
                }
                if (identifiedProperty != null)
                {
                    if (identifiedProperty.type == Property.PropertyType.LogicApp)
                    {
                        propertyObject["properties"]["value"] = $"[concat('sv=',{identifiedProperty.extraInfo}.queries.sv,'&sig=',{identifiedProperty.extraInfo}.queries.sig)]";
                    }
                    else if (identifiedProperty.type == Property.PropertyType.LogicAppRevisionGa)
                    {
                        propertyObject["properties"]["value"] = $"[{identifiedProperty.extraInfo}.queries.sig]";
                    }
                    else if (identifiedProperty.type == Property.PropertyType.Function)
                    {
                        //    "replacewithfunctionoperationname"
                        propertyObject["properties"]["value"] = $"[{identifiedProperty.extraInfo.Replace("replacewithfunctionoperationname", $"{identifiedProperty.operationName}")}]";
                    }
                    var propertyTemplate = template.AddProperty(propertyObject);

                    if (!parametrizePropertiesOnly)
                    {
                        string resourceid = $"[resourceId('Microsoft.ApiManagement/service/properties',{propertyTemplate.GetResourceId()})]";
                        foreach (var apiName in identifiedProperty.apis)
                        {
                            var apiTemplate = template.resources.Where(rr => rr.Value <string>("name") == apiName).FirstOrDefault();
                            if (apiTemplate != null)
                            {
                                apiTemplate.Value <JArray>("dependsOn").Add(resourceid);
                            }
                        }
                    }
                }
            }

            return(JObject.FromObject(template));
        }
        public async Task <JObject> GenerateTemplate()
        {
            DeploymentTemplate template = new DeploymentTemplate(this.parametrizePropertiesOnly);

            if (exportPIManagementInstance)
            {
                var apim = await resourceCollector.GetResource(GetAPIMResourceIDString());

                template.AddAPIManagementInstance(apim);
            }

            var apis = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

            foreach (JObject apiObject in (apis == null ? new JArray() : apis.Value <JArray>("value")))
            {
                var id = apiObject.Value <string>("id");


                var apiInstance = await resourceCollector.GetResource(id);

                var apiTemplateResource = template.AddApi(apiInstance);

                //Api version set
                string apiversionsetid = apiTemplateResource["properties"].Value <string>("apiVersionSetId");
                if (!string.IsNullOrEmpty(apiversionsetid))
                {
                    AzureResourceId aiapiversion = new AzureResourceId(apiInstance["properties"].Value <string>("apiVersionSetId"));

                    var versionsetResource = template.AddVersionSet(await resourceCollector.GetResource(apiversionsetid));
                    if (versionsetResource != null)
                    {
                        string resourceid = $"[resourceId('Microsoft.ApiManagement/service/api-version-sets',{versionsetResource.GetResourceId()})]";
                        apiTemplateResource["properties"]["apiVersionSetId"] = resourceid;
                        apiTemplateResource.Value <JArray>("dependsOn").Add(resourceid);
                    }
                }



                var operations = await resourceCollector.GetResource(id + "/operations");

                foreach (JObject operation in (operations == null ? new JArray() : operations.Value <JArray>("value")))
                {
                    var opId = operation.Value <string>("id");

                    var operationInstance = await resourceCollector.GetResource(opId);

                    var operationTemplateResource = template.CreateOperation(operationInstance);
                    apiTemplateResource.Value <JArray>("resources").Add(operationTemplateResource);


                    var operationPolicies = await resourceCollector.GetResource(opId + "/policies");

                    foreach (JObject policy in (operationPolicies == null ? new JArray() : operationPolicies.Value <JArray>("value")))
                    {
                        var pol = template.CreatePolicy(policy);

                        //add properties
                        this.PolicyHandleProperties(pol, apiTemplateResource.Value <string>("name"), (operationInstance.Value <string>("name").StartsWith("api-") ? operationInstance.Value <string>("name").Substring(4, (operationInstance.Value <string>("name").LastIndexOf("-" + operationInstance["properties"].Value <string>("method").ToLower())) - 4): operationInstance.Value <string>("name")));

                        var operationSuffix = apiInstance.Value <string>("name") + "_" + operationInstance.Value <string>("name");
                        //Handle Azure Resources
                        if (!this.PolicyHandeAzureResources(pol, apiTemplateResource.Value <string>("name"), template))
                        {
                            PolicyHandeBackendUrl(pol, operationSuffix, template);
                        }

                        var backendid = TemplateHelper.GetBackendIdFromnPolicy(policy["properties"].Value <string>("policyContent"));

                        if (!string.IsNullOrEmpty(backendid))
                        {
                            JObject backendInstance = await HandleBackend(template, operationSuffix, backendid);

                            if (apiTemplateResource.Value <JArray>("dependsOn") == null)
                            {
                                apiTemplateResource["dependsOn"] = new JArray();
                            }

                            //add dependeOn
                            apiTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/backends', parameters('service_{servicename}_name'), '{backendInstance.Value<string>("name")}')]");
                        }

                        operationTemplateResource.Value <JArray>("resources").Add(pol);
                        //handle nextlink?
                    }
                    //handle nextlink?
                }

                var apiPolicies = await resourceCollector.GetResource(id + "/policies");

                foreach (JObject policy in (apiPolicies == null ? new JArray() : apiPolicies.Value <JArray>("value")))
                {
                    //Handle SOAP Backend
                    var backendid = TemplateHelper.GetBackendIdFromnPolicy(policy["properties"].Value <string>("policyContent"));


                    var policyTemplateResource = template.CreatePolicy(policy);
                    PolicyHandeBackendUrl(policy, apiInstance.Value <string>("name"), template);
                    this.PolicyHandleProperties(policy, apiTemplateResource.Value <string>("name"), null);
                    apiTemplateResource.Value <JArray>("resources").Add(policyTemplateResource);



                    if (!string.IsNullOrEmpty(backendid))
                    {
                        JObject backendInstance = await HandleBackend(template, apiObject.Value <string>("name"), backendid);

                        if (apiTemplateResource.Value <JArray>("dependsOn") == null)
                        {
                            apiTemplateResource["dependsOn"] = new JArray();
                        }

                        //add dependeOn
                        apiTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/backends', parameters('service_{servicename}_name'), '{backendInstance.Value<string>("name")}')]");
                    }

                    //handle nextlink?
                }
                //schemas
                var apiSchemas = await resourceCollector.GetResource(id + "/schemas");

                foreach (JObject schema in (apiSchemas == null ? new JArray() : apiSchemas.Value <JArray>("value")))
                {
                    var schemaTemplate = template.CreateAPISchema(schema);
                    apiTemplateResource.Value <JArray>("resources").Add(JObject.FromObject(schemaTemplate));
                }

                //handle nextlink?
            }

            // Export all groups if we don't export the products.
            if (exportGroups && !exportProducts)
            {
                var groups = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/groups");

                foreach (JObject groupObject in (groups == null ? new JArray() : groups.Value <JArray>("value")))
                {
                    //cannot edit och create built in groups
                    if (groupObject["properties"].Value <bool>("builtIn") == false)
                    {
                        template.AddGroup(groupObject);
                    }
                }
            }

            if (exportProducts)
            {
                var products = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/products");

                foreach (JObject productObject in (products == null ? new JArray() : products.Value <JArray>("value")))
                {
                    var id = productObject.Value <string>("id");
                    var productInstance = await resourceCollector.GetResource(id);

                    var productApis = await resourceCollector.GetResource(id + "/apis", (string.IsNullOrEmpty(apiFilters) ? "" : $"$filter={apiFilters}"));

                    // Skip product if not related to an API in the filter.
                    if (productApis != null && productApis.Value <JArray>("value").Count > 0)
                    {
                        var productTemplateResource = template.AddProduct(productObject);

                        foreach (JObject productApi in (productApis == null ? new JArray() : productApis.Value <JArray>("value")))
                        {
                            productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(productApi));
                        }

                        var groups = await resourceCollector.GetResource(id + "/groups");

                        foreach (JObject group in (groups == null ? new JArray() : groups.Value <JArray>("value")))
                        {
                            if (group["properties"].Value <bool>("builtIn") == false)
                            {
                                // Add group resource
                                var groupObject = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/groups/" + group.Value <string>("name"));

                                template.AddGroup(groupObject);
                                productTemplateResource.Value <JArray>("resources").Add(template.AddProductSubObject(group));
                                productTemplateResource.Value <JArray>("dependsOn").Add($"[resourceId('Microsoft.ApiManagement/service/groups', parameters('service_{servicename}_name'), '{group.Value<string>("name")}')]");
                            }
                        }
                    }
                }
            }

            var properties = await resourceCollector.GetResource(GetAPIMResourceIDString() + "/properties");

            foreach (JObject propertyObject in (properties == null ? new JArray() : properties.Value <JArray>("value")))
            {
                var id   = propertyObject.Value <string>("id");
                var name = propertyObject["properties"].Value <string>("displayName");

                var identifiedProperty = this.identifiedProperties.Where(idp => name.EndsWith(idp.name)).FirstOrDefault();
                if (identifiedProperty != null)
                {
                    if (identifiedProperty.type == Property.PropertyType.LogicApp)
                    {
                        propertyObject["properties"]["value"] = $"[concat('sv=',{identifiedProperty.extraInfo}.queries.sv,'&sig=',{identifiedProperty.extraInfo}.queries.sig)]";
                    }
                    else if (identifiedProperty.type == Property.PropertyType.LogicAppRevisionGa)
                    {
                        propertyObject["properties"]["value"] = $"[{identifiedProperty.extraInfo}.queries.sig]";
                    }
                    else if (identifiedProperty.type == Property.PropertyType.Function)
                    {
                        //    "replacewithfunctionoperationname"
                        propertyObject["properties"]["value"] = $"[{identifiedProperty.extraInfo.Replace("replacewithfunctionoperationname",$"{identifiedProperty.operationName}")}]";
                    }
                    var propertyTemplate = template.AddProperty(propertyObject);

                    if (!parametrizePropertiesOnly)
                    {
                        string resourceid = $"[resourceId('Microsoft.ApiManagement/service/properties',{propertyTemplate.GetResourceId()})]";
                        foreach (var apiName in identifiedProperty.apis)
                        {
                            var apiTemplate = template.resources.Where(rr => rr.Value <string>("name") == apiName).FirstOrDefault();
                            apiTemplate.Value <JArray>("dependsOn").Add(resourceid);
                        }
                    }
                }
            }

            return(JObject.FromObject(template));
        }