Initialization logic of a Azure ARM solution template without VM resource - azure

Is it possible to have an ARM solution template (createUiDefinition.json, azuredeploy.json, etc) published to Azure Marketplace, which have an App Service and a CosmosDB account resources but does not has any VM resources to have initialization logic (e.g. creation of CosmosDB database, collections) which executes once solution template is deployed.
In case if solution template contained VM, then it would be possible to use a Custom Script Extension, but is there a way without VMs?

I'm not sure what are you exactly after, but we are using Azure Function as a part of an arm template to configure cosmosDb. here is how it works:
"uri": "[concat('https://functionUrl?param1=', parameters('cosmosName'), '&param2=', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('cosmosName')), '2016-03-31').primaryMasterKey, '&code=', parameters('functionKey'))]"
this will call Azure Function and give it the cosmosDb name and key and you can use that in your Azure Function to connect to cosmosDb and configure it. the only caveat is your function should return empty template (or not empty, just parseable by the engine).
var template = #"{'$schema': 'https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#', 'contentVersion': '1.0.0.0', 'parameters': {}, 'variables': {}, 'resources': []}";
HttpResponseMessage myResponse = req.CreateResponse(HttpStatusCode.OK);
myResponse.Content = new StringContent(template, System.Text.Encoding.UTF8, "application/json");
return myResponse;

Related

How to get Azure App Configuration feature flag value list in bicep template

I would like to get list of already created feature flags from Azure App Configuration in bicep template. I want to pass it to separate bicep file that will use union function on existing and new feature flags to not override already existing ones.
Simillar thing I'm already using for Web App and list() function get existing app settings:
module appConfig './webappsettings.bicep' = {
name: '${deployment().name}-appSettings'
params: {
webAppName: webapp.name
currentAppSettings: list('${webapp.id}/config/appsettings', '2021-03-01').properties
appSettings: allSettings
}
}
How can I achieve something similar for Azure App Configuration to get key values of feature flags?
I tried with below solution but I only got key values of App Configuration
resource configurationStore 'Microsoft.AppConfiguration/configurationStores#2021-10-01-preview' existing = {
name: 'appcfg'
}
module configStoreKeyValues 'inner.bicep' = {
name: 'config-store'
params: {
existingKeyValues: configurationStore.listKeys().value
keyValues: keyValues
contentType: contentType
}
}
using same list() function or listKeys()
list('${configurationStore.id}/keyValues','2021-10-01-preview').properties
I'm getting an error:
Status Message: The resource namespace 'subscriptions' is invalid. (Code:InvalidResourceNamespace)
The "List" operation of key-values is not supported by the control-plane REST API in App Configuration. The listKeys API you used above returns the "Access keys", not the key-value configuration data you are looking for. You can create/update/read individual key-value, feature flag, Key Vault reference as KeyValues resource using Bicep. Feature flag is a special key-value with certain key prefix and content type. Below is an example of feature flag using the ARM template, but it should give you an idea of how to do the same in Bicep.
https://azure.microsoft.com/resources/templates/app-configuration-store-ff/
Note that the "List" operation of key-values is supported in the data-plane REST API of App Configuration. Besides the REST API, it's also accessible via Azure CLI, Azure portal, and App Configuration SDKs programmatically.

is there a way to create Generation 2 VM using Azure SDK?

Azure supports UEFI through Generation2 VM.
I am able to create a Generation2 VM using Azure web console, but I cannot a way to specify the generation of the VM through Azure SDK.
I have found a link in Microsoft Docs to create a manged disk using PowerCLI
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/generation-2#frequently-asked-questions
I looked into online documentation of Azure ComputeClient#virtual_machines#create_or_update() api. But still cannot find in the python code docs, any way to specify HyperVGenerations to the VM.
Yes. It's kind of counterintuitive but it goes like this: you need to specify the VM generation on the disk; then the VM, created off of this disk would be of that same generation.
If you already have a disk of gen2 then you just pick it up and specify it when creating the VM. However, I had to create the disk from a VHD file. So when you're creating the disk, you gonna need an IWithCreate instance and then chain a call to the WithHyperVGeneration method. Like this (C#):
public async Task<IDisk> MakeDisk(string vhdPath)
{
return await Azure.Disks.Define(name)
.WithRegion(Region.EuropeWest)
.WithExistingResourceGroup("my-resources")
.WithWindowsFromVhd(vhdPath)
.WithStorageAccount("saname")
.WithHyperVGeneration(HyperVGeneration.V2) // <--- This is how you specify the generation
.WithSku(DiskSkuTypes.PremiumLRS)
.CreateAsync();
}
Then create the VM:
var osDisk = await MakeDisk("template.vhd");
var vm = await Azure.VirtualMachines.Define("template-vm")
.WithRegion(Region.EuropWest)
.WithExistingResourceGroup("the-rg")
.WithExistingPrimaryNetworkInterface("some-nic")
.WithSpecializedOSDisk(osDisk, OperatingSystemTypes.Windows) // <-- Pay attention
.WithSize(VirtualMachineSizeTypes.StandardB2s)
.CreateAsync();

how to create azure batch pool based on custom VM image using java sdk

I want to use custom ubuntu VM image that I had created for by batch job. I can create a new pool by selecting the custom image from the azure portal itself but I wanted to write build script to do the same using the azure batch java sdk. This is what I was able to come up with:
List<NodeAgentSku> skus = client.accountOperations().listNodeAgentSkus().findAll({ it.osType() == OSType.LINUX })
String skuId = null
ImageReference imageRef = new ImageReference().withVirtualMachineImageId('/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Compute/images/$CUSTOM_VM_IMAGE_NAME')
for (NodeAgentSku sku : skus) {
for (ImageReference imgRef : sku.verifiedImageReferences()) {
if (imgRef.publisher().equalsIgnoreCase(osPublisher) && imgRef.offer().equalsIgnoreCase(osOffer) && imgRef.sku() == '18.04-LTS') {
skuId = sku.id()
break
}
}
}
VirtualMachineConfiguration configuration = new VirtualMachineConfiguration()
configuration.withNodeAgentSKUId(skuId).withImageReference(imageRef)
client.poolOperations().createPool(poolId, poolVMSize, configuration, poolVMCount)
But I am getting exception:
Caused by: com.microsoft.azure.batch.protocol.models.BatchErrorException: Status code 403, {
"odata.metadata":"https://analyticsbatch.eastus.batch.azure.com/$metadata#Microsoft.Azure.Batch.Protocol.Entities.Container.errors/#Element","code":"AuthenticationFailed","message":{
"lang":"en-US","value":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:bf9bf7fd-2ef5-497b-867c-858d081137e6\nTime:2019-04-17T23:08:17.7144177Z"
},"values":[
{
"key":"AuthenticationErrorDetail","value":"The specified type of authentication SharedKey is not allowed when external resources of type Compute are linked."
}
]
}
I definitely think the way I am getting the skuId is wrong. Since client.accountOperations().listNodeAgentSkus() does not list the custom image, I just thought of giving skuId based of the ubuntu version that I had used to create the custom image.
So what is the correct way to create pool using custom VM image for azure batch account using java sdk?
You must use Azure Active Directory credentials in order to create a pool with a custom image. It is in the prerequisites section of the Batch Custom Image doc.
This is a frequently asked question:
Custom Image under AzureBatch ImageReference class not working
Azure Batch Pool: How do I use a custom VM Image via Python?
Just shows as the error, you need to authenticate to Azure first and then you could create the pool with a custom image as you want.
First, you need an Azure Batch Account, you can create it in the Azure portal or using Azure CLI. Or you also can create the batch account through Java. See Manage the Azure Batch Account through Java.
Then I think you also need to authenticate to your batch account. There are two ways below:
Use the account name, key, and URL to create a BatchSharedKeyCredentials instance for authentication with the Azure Batch service. The BatchClient class is the simplest entry point for creating and interacting with Azure Batch objects.
BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(batchUri, batchAccount, batchKey);
BatchClient client = BatchClient.open(cred);
The other way is using AAD (Azure Active Directory) authentication to create the client. See this document for detail.
BatchApplicationTokenCredentials cred = new BatchApplicationTokenCredentials(batchEndpoint, clientId, applicationSecret, applicationDomain, null, null);
BatchClient client = BatchClient.open(cred);
Then you can create the pool with the custom as you want. Just like this:
System.out.println("Created a pool using an Azure Marketplace image.");
VirtualMachineConfiguration configuration = new VirtualMachineConfiguration();
configuration.withNodeAgentSKUId(skuId).withImageReference(imageRef);
client.poolOperations().createPool(poolId, poolVMSize, configuration, poolVMCount);
System.out.println("Created a Pool: " + poolId);
For more details, see Azure Batch Libraries for Java.

Azure Template reference function does not work for existing resource (not in template)

trying to use reference function in my ARM template for a resource that is already existing, but not included in my template. This does not seem to work. Is there some way to do this?
In particular, I'm deploy a new SQL database to an existing SQL server, along with a new webapp. In the web app, I'm trying to set connection string using
reference(concat('Microsoft.Sql/servers/', variables('sqlserverName'))).fullyQualifiedDomainName
but this doesnot work - says the resource is not available/included.
For reference function to work on existing resources you need to pass in the API versiĆ³n. Documentation.
apiVersion - API version of the specified resource. Include this parameter when the resource is not provisioned within same template. Typically, in the format, yyyy-mm-dd.
reference(parameters('storageAccountName'), '2016-12-01')

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