ARM Template listkeys() fails to find Azure Search - azure

I'm creating an ARM Template to deploy both an Azure Search instance and a Function App that depends on the Azure Search instance. As part of that I'm trying to pre-populate the Function Apps app settings with the Search Service's API Key.
I'm doing this by adding the following into the value of one of the app settings of the FunctionAppSite:
[listKeys(variables('searchServiceId'), '2015-08-19').key1]
I get the searchServiceId in the variables sections
[resourceId('Microsoft.Search/searchServices', parameters('SearchServiceName'))]
The FunctionAppSite component lists dependencies on the AppServicePlan, StorageAccount and SearchService.
When I deploy the template the Search Service gets created then an error occurs because listkeys couldn't find the Search Service. This happens about .25s after the service is created.
I'm pretty sure I have the syntax around the listkeys correct and the problem is just the timing, no sure how I can slow it down though. I tried forcing the StorageAccount to depend on the SearchService in my template, hoping the dependency chain would slow things down enough, but the listkeys error happens after the Search Service is created, but before the StorageAccount is created.
The full template can be found here and there is a 'Deploy to Azure' button on the readme.md of that repo if you want to see it in action.

Well, looking at provider operations for Microsoft.Search:
Microsoft.Search/register/action
Microsoft.Search/checkNameAvailability/action
Microsoft.Search/searchServices/write
Microsoft.Search/searchServices/read
Microsoft.Search/searchServices/delete
Microsoft.Search/searchServices/start/action
Microsoft.Search/searchServices/stop/action
Microsoft.Search/searchServices/listAdminKeys/action
Microsoft.Search/searchServices/regenerateAdminKey/action
Microsoft.Search/searchServices/createQueryKey/action
Microsoft.Search/searchServices/queryKey/read
Microsoft.Search/searchServices/queryKey/delete
this is how you do it:
"[listAdminKeys(variables('searchServiceId'), '2015-08-19').PrimaryKey]"
To list provider operations:
$ops = (Get-AzureRmProviderOperation -OperationSearchString */*).Operation

Related

SecureString in ARM template deployment through Terraform does an update in place everytime?

I am using Terraform to provision my Azure resources which works great, however, for some resources such as Logic Apps, doing this natively doesn't really work so I am using the Logic Apps ARM template and doing a Terraform "azurerm_resource_group_template_deployment" in order to provision. I know doing an ARM template deployment within Terraform is a bit of a last resort. It works ok though and deploys fine but I have a Service Bus connection defined and that is of type "securestring". By default, these are not saved as part of ARM deployment so everytime Terraform runs in my pipeline, even if the Logic App ARM template has not changed, it still does the deployment as the top level deployment state Terraform knows about previously did not have the value saved so will always see it as new. Is there any way around this other than changing the "securestring" to "string" which I obviously do not want to do given the endpoint contains the SAS key etc?
Hit same issues today - really limits what is viable. Managed to work around my two scenario's.
For things like keys and connection strings you can use the listkeys function inside of the ARM template - some examples here. I had this exact issue trying to get a log analytics workspace key in to the template - https://github.com/Azure/azure-quickstart-templates/blob/master/demos/arm-template-retrieve-azure-storage-access-keys/azuredeploy.json - Get connection strings in ARM
Another scenario I had was wanting to pass a service principal secret from TF to template as securestring, to get around this I ended up getting the secret from keyvault inside of the ARM template instead.

How to find the value for aadSessionkey when deploying a Kubernetes template in Azure DevOps

I am trying to use a template to deploy a managed Kubernetes cluster (AKS). My problem is that the template has a parameter aadSessionKey that I seem to be unable to locate.
I assume the expanded name of the parameter is Azure AD SessionKey. When I look in the portal, I can see that my Azure AD has a Name, Application ID and Object ID, but nothing that looks like a session key, nor a way to generate such a thing.
I am using a free trial account if that matters.
Can you try entering any random value and try deploying it. It seems like this is system generated value which is not to be filled by clients. This has been present in template for some other reason.
Ref - https://twitter.com/ashtonkj/status/1196384865672925184

Is there a way trigger "http trigger" azure function, after deploy ARM template?

I have ARM who deploy kubernetes cluster and httptrigger function app. Inside httptrigger func I have client for kubernetes who do some action if I trigger this func manually, its work fine. But I need run this trigger automatically after deploy ARM was finished.
The HTTP request that triggers the Azure Function may be sent either by ARM itself or by whatever orchestrator you use to execute the template (e.g. Azure DevOps pipeline). Terraform can execute scripts directly; unless you really want to use ARM, it might be an option.
If you want to go with ARM, there are at least three options:
Make the Azure Function return an "empty" ARM template and trigger it by a request for a nested deployment template. https://blog.cloudtrooper.net/2017/04/04/run-azure-functions-from-your-quickstart-arm-templates/
Use Azure Container Instances to launch an instance of a container image as a stand-alone container in Azure and execute an arbitrary command inside. https://samcogan.com/run-scripts-in-arm-deployments-with-aci/
Use the deployment scripts resource (Microsoft.Resources/deploymentScripts). It is basically built-in support for the approach using Azure Container Instances. See the official docs or an older article from the time the feature was still in preview that I still like: https://dev.to/omiossec/arm-template-what-s-new-for-2020-4kli#deployementsscripts-resource-provider
In any case, you will need to properly set up the dependsOn references so that the request is sent at the right time. Or better, use Bicep that mostly takes care of the dependencies implicitly, if used right.
Assuming you are using Powershell to deploy your ARM template, you can use Powershell to trigger your azure http trigger function right after you deploy your ARM template:
Invoke-WebRequest -Uri <function_uri> -Method POST
Hope this helps!

How can I programatically (C#) read the autoscale settings for a WebApp?

I'm trying to build a small program to change the autoscale settings for our Azure WebApps, using the Microsoft.WindowsAzure.Management.Monitoring and Microsoft.WindowsAzure.Management.WebSites NuGet packages.
I have been roughly following the guide here.
However, we are interested in scaling WebApps / App Services rather than Cloud Services, so I am trying to use the same code to read the autoscale settings but providing a resource ID for our WebApp. I have already got the credentials required for making a connection (using a browser window popup for Active Directory authentication, but I understand we can use X.509 management certificates for non-interactive programs).
This is the request I'm trying to make. Credentials already established, and an exception is thrown earlier if they're not valid.
AutoscaleClient autoscaleClient = new AutoscaleClient(credentials);
var resourceId = AutoscaleResourceIdBuilder.BuildWebSiteResourceId(webspaceName: WebSpaceNames.NorthEuropeWebSpace, serverFarmName: "Default2");
AutoscaleSettingGetResponse get = autoscaleClient.Settings.Get(resourceId); // exception here
The WebApp (let's call it "MyWebApp") is part of an App Service Plan called "Default2" (Standard: 1 small), in a Resource Group called "WebDevResources", in the North Europe region. I expect that my problem is that I am using the wrong names to build the resourceId in the code - the naming conventions in the library don't map well onto what I can see in the Azure Portal.
I'm assuming that BuildWebSiteResourceId is the correct method to call, see MSDN documentation here.
However the two parameters it takes are webspaceName and serverFarmName, neither of which match anything in the Azure portal (or Google). I found another example which seemed to be using the WebApp's geo region for webSpaceName, so I've used the predefined value for North Europe where our app is hosted.
While trying to find the correct value for serverFarmName in the Azure Portal, I found the Resource ID for the App Service Plan, which looks like this:
/subscriptions/{subscription-guid}/resourceGroups/WebDevResources/providers/Microsoft.Web/serverfarms/Default2
That resource ID isn't valid for the call I'm trying to make, but it does support the idea that a 'serverfarm' is the same as an App Service Plan.
When I run the code, regardless of whether the resourceId parameters seem to be correct or garbage, I get this error response:
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
{"Code":"SettingNotFound","Message":"Could not find the autoscale settings."}
</string>
So, how can I construct the correct resource ID for my WebApp or App Service Plan? Or alternatively, is there a different tree I should be barking up to programatially manage WebApp scaling?
Update:
The solution below got the info I wanted. I also found the Azure resource explorer at resources.azure.com extremely useful to browse existing resources and find the correct names. For example, the name for my autoscale settings is actually "Default2-WebDevResources", i.e. "{AppServicePlan}-{ResourceGroup}" which I wouldn't have expected.
There is a preview service https://resources.azure.com/ where you can inspect all your resources easily. If you search for autoscale in the UI you will easily find the settings for your resource. It will also show you how to call the relevant REST Api endpoint to read or update that resorce.
It's a great tool for revealing a lot of details for your deployed resources and it will actually give you an ARM template stub for the resource you are looking at.
And to answer your question, you could programmatically call the REST API from a client with updated settings for autoscale. The REST API is one way of doing this, the SDK another and PowerShell a third.
The guide which you're following is based on the Azure Service Management model, aka Classic mode, which is deprecated and only exists mainly for backward compatibility support.
You should use the latest
Microsoft.Azure.Insights nuget package for getting the autoscale settings.
Sample code using the nuget above is as below:
using Microsoft.Azure.Management.Insights;
using Microsoft.Rest;
//... Get necessary values for the required parameters
var client = new InsightsManagementClient(new TokenCredentials(token));
client.AutoscaleSettings.Get(resourceGroupName, autoScaleSettingName);
Besides, the autoscalesettings is a resource under the "Microsoft.Insights" provider and not under the "Microsoft.Web" provider, which explains why you are not able to find it with your serverfarm resourceId.
See the REST API Reference below for getting the autoscale settings.
GET
https://management.azure.com/subscriptions/{subscription-id}/resourceGroups/{resource-group-name}/providers/microsoft.insights/autoscaleSettings/{autoscale-setting-name}?api-version={api-version}

Cannot connect to DocumentDb directly after having deployed the DocumentDb account

I have an ARM template that I use to deploy a DocumentDB as well as other Azure reosurces to a resource group. I want my ARM template to setup a Stream Analytics job that uses the DocumentDB as output. In order to do this the DocumentDB account created by the ARM template needs to have a database and a collection setup as well. I cannot find a way to do this from an ARM template so I have written a Powershell CmdLet to create the database and collction for me.
The Stream Analytics job cannot be created by the first ARM template since it depends on having the database and collection created first. Instead I have to divide the deployment into two ARM templates, the first setting up the DocDb account and the second setting up the SA job.
The problem is that I cannot create a database in the DocDB account directly after having deployed the account via the ARM template. I get an exception with the following message: "The remote name could not be resolved: 'test.documents.azure.com'" when I try to execute the CreateDatabaseAsync method with the DocDbEndpoint and AuthKey I get back from the ARM template deployment.
Are there any timing issues after having deployed Azure resources using a ARM template before you can access them programatically? This do not seem to be a problem with other Azure reosurces created this way.
Any help on this matter is highly appreciated as well as what is a good practice for working with ARM templates with DocumentDB and Stream Analytic jobs.
Update 2016-03-23
Code for setting up the connection to the DocumentDB to create the database.
Uri endpointUri = new Uri(documentDbEndPoint);
DocumentClient client = new DocumentClient(endpointUri, authKey);
var db = await client.CreateDatabaseAsync(new Database { Id = databaseId });
return db;
Where the documentDbEndPoint is in the form of: https://name.documents.azure.com:443/ and name is the name of my DocDB account just created by the ARM template deployment.
I have the code in a library which I can either call from a Console application or from a Powershell script by loading the library with:
Add-Type -Path <path to library dll file>
No matter if I use powershell or console application I get the same error if I try to create a database just after having created the DocDB account using the ARM template. If I wait like an hour or so both the powershell script and console application works and can create a database in the account.
Seems like there is some kind of timing issue in order for Azure to setup dns records for the newly created DocDB account so that it can be accessed using the DocDB API.
Update 2 2016-03-23
Just tried to create a DocDB account directly from the portal and doing this instead of creating it from an ARM template makes it possible to create a database in the account using my powershell script and console application immediately.
This timing issue has been fixed now and you should be able to use it from the ARM template now.

Resources