This is part 2 of my learning adventure of Farmer for Azure resource deployments. This time, I wanted to look at parameters, variables, outputs and expressions.
Passing Outputs to another Resource
I created a Web App with a dependency to a storage account. As shown below, the storage key kan simply be passed to the web application.
let sa = storageAccount {
name "demo-sma75-sa"
}
let webAppConfig = webApp {
name "demo-webapp"
setting "storageKey" sa.Key
}
The generated ARM template shows us the storage key.
"appSettings": [
{
"name": "storageKey",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=demosma75sa;AccountKey=', listKeys('demosma75sa', '2017-10-01').keys[0].value)]"
},
Farmer knows that the Web Application needs to be deployed before the storage account, so we don’t need to explicitly declare this. However, you can specify this explicitly with depends_on
.
let webAppConfig = webApp {
name "demo-webapp"
setting "storageKey" sa.Key
depends_on [ sa ]
}
depends_on [ sa ]
gave me this error message.
/Users/sma/git/farmer-demo1/Program.fs(12,5): error FS0041: No overloads match for method 'DependsOn'.Known types of arguments: WebAppConfig * StorageAccountConfig listAvailable overloads: - member WebAppBuilder.DependsOn : state:WebAppConfig * builder:CoreTypes.IBuilder -> WebAppConfig // Argument 'builder' doesn't match - member WebAppBuilder.DependsOn : state:WebAppConfig * resource:CoreTypes.IArmResource -> WebAppConfig // Argument 'resource' doesn't match - member WebAppBuilder.DependsOn : state:WebAppConfig * resourceName:CoreTypes.ResourceName -> WebAppConfig // Argument 'resourceName' doesn't match [/Users/sma/git/farmer-demo1/FarmerApp.fsproj]
I do not know F# yet, so this error might be obvious for others, but I have an idea how to solve this (part of a later post). For me it was just painful because my example is directly from the documentation.
Anyway, the storage key was successfully set under Application Settings.
App Service setting with storage key
Looking at the API for Web App we see all the configurations we can and have to set if we want to understand what happens and gets created. I.e. can we set app_insights_off
to avoid creating an instance for us.
Created Azure resources with Farmer for default WebApp
No Support for Variables and Parameters
Farmer doesn’t support ARM variables or parameters. The reasons for that are:
- Codebase gets more complex
- API surface area gets more complex
- Expressions capabilities inside ARM templates like concat inside a variable that depends on another variable - hard to do without increasing the complexity
The Farmer developers recommend to put Farmer as part of a build script to generate ARM templates, rather than committing into source control.
- Simplifies the code base
- Instead of using the error prone and limited expression capabilities of ARM templates, you can use a proper programming language for conditional logic for creating the ARM template
- Deployments e.g. inside the Azure Portal are much easier to read because there are no placeholders or variables but just values
Here’s the code for entire application
open Farmer
open Farmer.Builders
open System
let createWebApp theLocation =
let sa = storageAccount {
name "demo-sma-sa"
}
let webapp = webApp {
name "demo-sma75-webapp"
app_insights_off
setting "storageKey" sa.Key
}
arm {
// Our location we set previously
location theLocation
add_resource sa
add_resource webapp
}
createWebApp Location.WestEurope
|> Deploy.execute "farmer-rg" Deploy.NoParameters
Next Steps
This example was pretty basic, but it might show that we can pass parameters as input values and all created resources get the location set with the actual value rather then a reference. What interests me next is how I can deploy Azure App Configuration or Azure API Management with Farmer. Those resources are not part of Farmer yet.