Octopus.AzurePowerShell exported 2023-11-30 by harrisonmeister belongs to ‘Azure’ category.
This step retrieves one or more key/values from an Azure App Configuration store and adds them to an Azure App Function’s AppSettings.
You can retrieve individual keys that match a specific name, and you can choose a custom setting name for each key.
Wildcard search is also supported using the *
notation in the Key Names parameter. Note: Combining a wildcard search with custom setting names is not supported.
You can also combine retrieved values with additional parameters passed into the step using the Additional AppSettings
parameter.
Authentication is performed using an Azure Service Principal.
Required:
- An Azure account with permission to both retrieve values from the Azure App Config store and publish to the App Function.
- The
az
CLI on the target or worker. If the CLI can’t be found, the step will fail.
Notes:
- Tested on Octopus
2024.1
using az version2.38.0
- Tested with both Windows PowerShell and PowerShell Core (on Linux).
- Slot Settings are not currently supported.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Azure Account
AzFunction.SetAppSettings.FromAzAppConfig.AzureAccount =
An Azure account with permission to both retrieve values from the Azure App Config store and publish to the App Function
Config Store Name
AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreName =
The name of the Azure App Configuration store. Provide this or the Config store endpoint.
Config Store Endpoint
AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreEndpoint =
The endpoint for the Azure App Configuration Store. Provide this or the Config store name.
Retrieval Method
AzFunction.SetAppSettings.FromAzAppConfig.RetrievalMethod = all
Choose how the step calls the az cli. Either:
All
: Retrieve all configuration values in one callIndividually
: Retrieve configuration values in multiple calls; one for each key specified in the Key Names parameter.
Default: All
Key Names
AzFunction.SetAppSettings.FromAzAppConfig.KeyNames =
Specify the names of the keys to be returned from Azure App Configuration in the format KeyName | CustomSettingName
where:
KeyName
is the key to retrieve. Wildcards are supported by adding*
at the end of the key name.CustomSettingName
is the optional name to set for the AppSetting value in the App Function. If this value isn’t specified, the original key will be used..
Note: Multiple keys can be retrieved by entering each one on a new line. Note: Combining a wildcard search with custom setting names is not supported.
Labels
AzFunction.SetAppSettings.FromAzAppConfig.Labels =
Labels are an attribute on keys. Provide one or more labels in the format label1,label2
to retrieve only selected keys tagged with those labels.
Note: You can include both label values and specify key names if you want.
Suppress warnings
AzFunction.SetAppSettings.FromAzAppConfig.SuppressWarnings = False
Suppress warnings from being written to the task log. For example, when a supplied key can’t be found in the Azure App Configuration store.
Treat Warnings as Errors
AzFunction.SetAppSettings.FromAzAppConfig.TreatWarningsAsErrors = True
Treats warnings as errors. If enabled the Suppress Warnings parameter is ignored.
Azure Function App Name
AzFunction.SetAppSettings.FromAzAppConfig.FunctionName =
The name of the Azure App function.
Resource Group
AzFunction.SetAppSettings.FromAzAppConfig.ResourceGroup =
The name of the resource group where the Function App is located.
Slot
AzFunction.SetAppSettings.FromAzAppConfig.Slot =
The name of the slot. Defaults to the production slot if not specified.
Additional AppSettings
AzFunction.SetAppSettings.FromAzAppConfig.AdditionalSettingsValues =
Specify the name and values of any additional settings to be applied to the Azure App Function in the format KEY | VALUE
where:
KEY
is the name of the app setting to addVALUE
is the value to be used. Octopus variables can be used here.
Note: Multiple settings can be added by entering each one on a new line. As a result, values that span multiple lines will result in an error.
Script body
Steps based on this template will execute the following PowerShell script.
$ErrorActionPreference = 'Stop'
# KV Variables
$global:AzureAppConfigStoreName = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreName"]
$global:AzureAppConfigStoreEndpoint = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreEndpoint"]
$global:AzureAppConfigRetrievalMethod = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.RetrievalMethod"]
$ConfigStoreKeyNames = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.KeyNames"]
$global:ConfigStoreLabels = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.Labels"]
$global:SuppressWarnings = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.SuppressWarnings"] -ieq "True"
$global:TreatWarningsAsErrors = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.TreatWarningsAsErrors"] -ieq "True"
# Function Variables
$FunctionName = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.FunctionName"]
$ResourceGroup = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.ResourceGroup"]
$AdditionalSettingsValues = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.AdditionalSettingsValues"]
$Slot = $OctopusParameters["AzFunction.SetAppSettings.FromAzAppConfig.Slot"]
# KV params validation
if ([string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreName) -and [string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreEndpoint)) {
throw "Either parameter ConfigStoreName or ConfigStoreEndpoint not specified"
}
if ([string]::IsNullOrWhiteSpace($global:AzureAppConfigRetrievalMethod)) {
throw "Required parameter AzFunction.SetAppSettings.FromAzAppConfig.RetrievalMethod not specified"
}
if ([string]::IsNullOrWhiteSpace($ConfigStoreKeyNames) -and [string]::IsNullOrWhiteSpace($global:ConfigStoreLabels)) {
throw "Either AzFunction.SetAppSettings.FromAzAppConfig.KeyNames or AzFunction.SetAppSettings.FromAzAppConfig.Labels not specified"
}
# Function params validation
if ([string]::IsNullOrWhiteSpace($FunctionName)) {
throw "Required parameter AzureFunction.ConfigureAppSettings.FunctionName not specified"
}
if ([string]::IsNullOrWhiteSpace($ResourceGroup)) {
throw "Required parameter AzureFunction.ConfigureAppSettings.ResourceGroup not specified"
}
$RetrieveAllKeys = $global:AzureAppConfigRetrievalMethod -ieq "all"
$global:ConfigStoreParameters = ""
if (-not [string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreName)) {
$global:ConfigStoreParameters += " --name ""$global:AzureAppConfigStoreName"""
}
if (-not [string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreEndpoint)) {
$global:ConfigStoreParameters += " --endpoint ""$global:AzureAppConfigStoreEndpoint"""
}
### Helper functions
function Test-ForAzCLI() {
$oldPreference = $ErrorActionPreference
$ErrorActionPreference = "Stop"
try {
if (Get-Command "az") {
return $True
}
}
catch {
return $false
}
finally {
$ErrorActionPreference = $oldPreference
}
}
function Write-OctopusWarning(
[string] $Message
) {
if ($global:TreatWarningsAsErrors) {
throw "Error: $Message"
}
else {
if ($global:SuppressWarnings -eq $False) {
Write-Warning -Message $Message
}
else {
Write-Verbose -Message $Message
}
}
}
function Save-AppSetting(
[string]$settingName,
[string]$settingValue) {
$global:Settings += [PsCustomObject]@{name = $settingName; value = $settingValue; slotSetting = $false }
}
function Find-AzureAppConfigMatchesFromKey(
[string]$KeyName,
[bool]$IsWildCard,
[string]$settingName,
[PsCustomObject]$AppConfigValues) {
if ($IsWildCard -eq $False) {
Write-Verbose "Finding exact match for: $keyName"
$matchingAppConfigKeys = $appConfigValues | Where-Object { $_.key -ieq $keyName }
if ($null -eq $matchingAppConfigKeys -or $matchingAppConfigKeys.Count -eq 0) {
Write-OctopusWarning "Unable to find a matching key in Azure App Config for: $keyName"
}
else {
if ($matchingAppConfigKeys.Count -gt 1) {
Write-OctopusWarning "Found multiple matching keys ($($matchingAppConfigKeys.Count)) in Azure App Config for: $keyName. This is usually due to multiple values with labels"
foreach ($matchingAppConfigKey in $matchingAppConfigKeys) {
Write-Verbose "Found match for $keyName $(if(![string]::IsNullOrWhiteSpace($matchingAppConfigKey.content_type)) {"($($matchingAppConfigKey.content_type))"})"
$settingValue = $matchingAppConfigKey.value
if ([string]::IsNullOrWhiteSpace($settingName)) {
$settingName = $keyName.Trim()
}
if (![string]::IsNullOrWhiteSpace($matchingAppConfigKey.label)) {
$settingName = "$($keyName.Trim())-$($matchingAppConfigKey.label)"
Write-Verbose "Appending label to setting name to avoid duplicate setting: $settingName"
}
Save-AppSetting -settingName $settingName -settingValue $settingValue
}
}
else {
$matchingAppConfigKey = $matchingAppConfigKeys | Select-Object -First 1
Write-Verbose "Found match for $keyName $(if(![string]::IsNullOrWhiteSpace($matchingAppConfigKey.content_type)) {"($($matchingAppConfigKey.content_type))"})"
$settingValue = $matchingAppConfigKey.value
if ([string]::IsNullOrWhiteSpace($settingName)) {
$settingName = $keyName.Trim()
}
Save-AppSetting -settingName $settingName -settingValue $settingValue
}
}
}
else {
Write-Verbose "Finding wildcard match for: $keyName"
$matchingAppConfigKeys = @($appConfigValues | Where-Object { $_.key -ilike $keyName })
if ($matchingAppConfigKeys.Count -eq 0) {
Write-OctopusWarning "Unable to find any matching keys in Azure App Config for wildcard: $keyName"
}
else {
foreach ($match in $matchingAppConfigKeys) {
# Have to explicitly set settings as they are wildcard matches
$settingName = $match.key
$settingValue = $match.value
Write-Verbose "Found wildcard match '$settingName' $(if(![string]::IsNullOrWhiteSpace($matchingAppConfigKey.content_type)) {"($($matchingAppConfigKey.content_type))"})"
Save-AppSetting -settingName $settingName -settingValue $settingValue
}
}
}
}
function Find-AzureAppConfigMatchesFromLabels() {
Write-Verbose "Retrieving values matching labels: $global:ConfigStoreLabels"
$command = "az appconfig kv list $global:ConfigStoreParameters --label ""$global:ConfigStoreLabels"" --auth-mode login"
Write-Verbose "Invoking expression: $command"
$appConfigResponse = Invoke-Expression -Command $command
$ExitCode = $LastExitCode
Write-Verbose "az exit code: $ExitCode"
if ($ExitCode -ne 0) {
throw "Error retrieving appsettings. ExitCode: $ExitCode"
}
if ([string]::IsNullOrWhiteSpace($appConfigResponse)) {
Write-OctopusWarning "Null or empty response received from Azure App Configuration service"
}
else {
$appConfigValues = $appConfigResponse | ConvertFrom-Json
if ($appConfigValues.Count -eq 0) {
Write-OctopusWarning "Unable to find any matching keys in Azure App Config for labels: $global:ConfigStoreLabels"
}
else {
Write-Verbose "Finding match(es) for labels: $global:ConfigStoreLabels"
foreach ($appConfigValue in $appConfigValues) {
# Have to explicitly set setting Name here as its a match based on label alone
$settingName = $appConfigValue.key
Write-Verbose "Found label match '$($appConfigValue.key)' $(if(![string]::IsNullOrWhiteSpace($appConfigValue.content_type)) {"($($appConfigValue.content_type))"})"
if (![string]::IsNullOrWhiteSpace($appConfigValue.label)) {
$settingName = "$($settingName)-$($appConfigValue.label)"
Write-Verbose "Appending label to setting to avoid duplicate name: $settingName"
}
$settingValue = $appConfigValue.value
Save-AppSetting -settingName $settingName -settingValue $settingValue
}
}
}
}
# Check if Az cli is installed.
$azCliAvailable = Test-ForAzCLI
if ($azCliAvailable -eq $False) {
throw "Cannot find the Azure CLI (az) on the machine. This must be available to continue."
}
# Begin KV Retrieval
$Keys = @()
$global:Settings = @()
# Extract key names+optional custom setting name
@(($ConfigStoreKeyNames -Split "`n").Trim()) | ForEach-Object {
if (![string]::IsNullOrWhiteSpace($_)) {
Write-Verbose "Working on: '$_'"
$keyDefinition = ($_ -Split "\|")
$keyName = $keyDefinition[0].Trim()
$KeyIsWildcard = $keyName.EndsWith("*")
$settingName = $null
if ($keyDefinition.Count -gt 1) {
if ($KeyIsWildcard) {
throw "Key definition: '$_' evaluated as a wildcard with a custom setting name. This is not supported."
}
$settingName = $keyDefinition[1].Trim()
}
if ([string]::IsNullOrWhiteSpace($keyName)) {
throw "Unable to establish key name from: '$_'"
}
$key = [PsCustomObject]@{
KeyName = $keyName
KeyIsWildcard = $KeyIsWildcard
SettingName = if (![string]::IsNullOrWhiteSpace($settingName)) { $settingName } else { "" }
}
$Keys += $key
}
}
$LabelsArray = $global:ConfigStoreLabels -Split "," | Where-Object { [string]::IsNullOrWhiteSpace($_) -eq $False }
Write-Verbose "Azure AppConfig Retrieval Method: $global:AzureAppConfigRetrievalMethod"
if (![string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreName)) {
Write-Verbose "Azure AppConfig Store Name: $global:AzureAppConfigStoreName"
}
if (![string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreEndpoint)) {
Write-Verbose "Azure AppConfig Store Endpoint: $global:AzureAppConfigStoreEndpoint"
}
Write-Verbose "Suppress warnings: $global:SuppressWarnings"
Write-Verbose "Treat warnings as errors: $global:TreatWarningsAsErrors"
Write-Verbose "Keys to retrieve: $($Keys.Count)"
Write-Verbose "Labels to retrieve: $($LabelsArray.Count)"
$appConfigResponse = $null
# Retrieving all keys should be more performant, but may have a larger payload response.
if ($RetrieveAllKeys) {
if ($Keys.Count -gt 0) {
Write-Host "Retrieving ALL config values from store"
$command = "az appconfig kv list $global:ConfigStoreParameters --all --auth-mode login"
if (![string]::IsNullOrWhiteSpace($global:ConfigStoreLabels)) {
$command += " --label ""$global:ConfigStoreLabels"" "
}
Write-Verbose "Invoking expression: $command"
$appConfigResponse = Invoke-Expression -Command $command
$ExitCode = $LastExitCode
Write-Verbose "az exit code: $ExitCode"
if ($ExitCode -ne 0) {
throw "Error retrieving appsettings. ExitCode: $ExitCode"
}
if ([string]::IsNullOrWhiteSpace($appConfigResponse)) {
Write-OctopusWarning "Null or empty response received from Azure App Configuration service"
}
else {
$appConfigValues = $appConfigResponse | ConvertFrom-Json
}
foreach ($key in $Keys) {
$keyName = $key.KeyName
$KeyIsWildcard = $key.KeyIsWildcard
$SettingName = $key.SettingName
Find-AzureAppConfigMatchesFromKey -KeyName $keyName -IsWildcard $KeyIsWildcard -SettingName $SettingName -AppConfigValues $appConfigValues
}
}
# Possible that ONLY labels have been provided
elseif ($LabelsArray.Count -gt 0) {
Find-AzureAppConfigMatchesFromLabels
}
}
# Loop through and get keys based on the supplied names
else {
Write-Host "Retrieving keys based on supplied names..."
if ($Keys.Count -gt 0) {
foreach ($key in $Keys) {
$keyName = $key.KeyName
$KeyIsWildcard = $key.KeyIsWildcard
$settingName = $key.SettingName
if ([string]::IsNullOrWhiteSpace($settingName)) {
$settingName = "$($keyName.Trim())"
}
Write-Verbose "Retrieving values matching key: $keyName from store"
$command = "az appconfig kv list $global:ConfigStoreParameters --key ""$keyName"" --auth-mode login"
if (![string]::IsNullOrWhiteSpace($global:ConfigStoreLabels)) {
$command += " --label ""$global:ConfigStoreLabels"" "
}
Write-Verbose "Invoking expression: $command"
$appConfigResponse = Invoke-Expression -Command $command
$ExitCode = $LastExitCode
Write-Verbose "az exit code: $ExitCode"
if ($ExitCode -ne 0) {
throw "Error retrieving appsettings. ExitCode: $ExitCode"
}
if ([string]::IsNullOrWhiteSpace($appConfigResponse)) {
Write-OctopusWarning "Null or empty response received from Azure App Configuration service"
}
else {
$appConfigValues = $appConfigResponse | ConvertFrom-Json
if ($appConfigValues.Count -eq 0) {
Write-OctopusWarning "Unable to find a matching key in Azure App Config for: $keyName"
}
else {
Write-Verbose "Finding match(es) for: $keyName"
Find-AzureAppConfigMatchesFromKey -KeyName $keyName -IsWildcard $KeyIsWildcard -SettingName $settingName -AppConfigValues $appConfigValues
}
}
}
}
}
# End KV Retrieval
# Begin AZ Function set
$AdditionalSettings = @()
#$SlotSettings = @()
# Extract additional settings values
if (-not [string]::IsNullOrWhiteSpace($AdditionalSettingsValues)) {
@(($AdditionalSettingsValues -Split "`n").Trim()) | ForEach-Object {
if (![string]::IsNullOrWhiteSpace($_)) {
Write-Verbose "Working on: '$_'"
if (-not $_.Contains("|")) {
throw "Setting '$_' doesnt contain the '|' delimiter. Multi-line values aren't supported."
}
$settingDefinition = ($_ -Split "\|")
$settingName = $settingDefinition[0].Trim()
$settingValue = ""
if ($settingDefinition.Count -gt 1) {
$settingValue = $settingDefinition[1].Trim()
}
if ([string]::IsNullOrWhiteSpace($settingName)) {
throw "Unable to establish additional setting name from: '$_'"
}
$setting = [PsCustomObject]@{
name = $settingName
value = $settingValue
slotSetting = $false
}
$AdditionalSettings += $setting
}
}
}
if ($Settings.Count -gt 0 -or $AdditionalSettings.Count -gt 0) {
Write-Host "Settings found to publish to App Function: $FunctionName"
Write-Verbose "Function Name: $FunctionName"
Write-Verbose "Resource Group: $ResourceGroup"
Write-Verbose "Slot: $Slot"
Write-Verbose "Settings: $($Settings.Count)"
Write-Verbose "Additional Settings: $($AdditionalSettings.Count)"
if ($AdditionalSettings.Count -gt 0) {
Write-Verbose "Combining additional settings with settings retrieved from Azure App Config"
$Settings = $Settings + $AdditionalSettings
}
$settingsFile = $null
try {
$command = "az functionapp config appsettings set --name=""$Functionname"" --resource-group ""$ResourceGroup"" "
if (-not([string]::IsNullOrWhiteSpace($Slot))) {
$command += " --slot ""$Slot"" "
}
if ($Settings.Count -ge 1) {
$settingsFile = [System.IO.Path]::GetRandomFileName()
$ConvertToJsonParameters = @{}
if ($PSVersionTable.PSVersion.Major -ge 6) {
$ConvertToJsonParameters.Add("AsArray", $True)
}
$Settings | ConvertTo-Json @ConvertToJsonParameters | Set-Content -Path $settingsFile
$command += " --settings '@$settingsFile'"
}
Write-Verbose "Invoking expression: $command"
Write-Host "##octopus[stderr-progress]"
$settingsUpdateResponse = Invoke-Expression -Command $command
$ExitCode = $LastExitCode
Write-Verbose "FunctionApp update ExitCode: $ExitCode"
if ($ExitCode -ne 0) {
throw "Error configuring appsettings for function app '$FunctionName'. ExitCode: $ExitCode"
}
Write-Host "##octopus[stderr-default]"
if ($null -ne $settingsUpdateResponse) {
Write-Host "Update of function '$FunctionName' was successful"
try {
$functionSettings = $settingsUpdateResponse | ConvertFrom-Json
if ($null -ne $functionSettings) {
$settingsCount = @($functionSettings | Where-Object { $_.slotSetting -eq $False }).Count
$slotSettingsCount = @($functionSettings | Where-Object { $_.slotSetting -eq $True }).Count
Write-Verbose "Function '$FunctionName' has $settingsCount setting(s) and $slotSettingsCount slot setting(s)."
}
}
catch {}
}
}
catch { throw }
finally {
if (-not([string]::IsNullOrWhiteSpace($settingsFile))) {
Write-Verbose "Removing temporary settings file $settingsFile"
Remove-Item -Path $settingsFile -Force -ErrorAction Ignore
}
if (-not([string]::IsNullOrWhiteSpace($slotSettingsFile))) {
Write-Verbose "Removing temporary slot settings file $slotSettingsFile"
Remove-Item -Path $slotSettingsFile -Force -ErrorAction Ignore
}
}
}
else {
Write-Host "No settings found to publish to the Azure App function"
}
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "67fcc93c-509c-4c13-bc24-645eff53c5c2",
"Name": "Azure Function - Set AppSettings from Azure AppConfig",
"Description": "This step retrieves one or more key/values from an Azure App Configuration store and adds them to an Azure App Function's AppSettings.\n\nYou can retrieve individual keys that match a specific name, and you can choose a custom setting name for each key.\n\nWildcard search is also supported using the `*` notation in the **Key Names** parameter. Note: Combining a wildcard search with custom setting names is not supported.\n\nYou can also combine retrieved values with additional parameters passed into the step using the `Additional AppSettings` parameter.\n\nAuthentication is performed using an Azure Service Principal.\n\n---\n\n**Required:** \n- An Azure account with permission to both retrieve values from the Azure App Config store and publish to the App Function.\n- The `az` CLI on the target or worker. If the CLI can't be found, the step will fail. \n\nNotes:\n\n- Tested on Octopus `2024.1` using az version `2.38.0`\n- Tested with both Windows PowerShell and PowerShell Core (on Linux).\n- Slot Settings are not currently supported.",
"Version": 3,
"ExportedAt": "2023-11-30T16:25:08.828Z",
"ActionType": "Octopus.AzurePowerShell",
"Author": "harrisonmeister",
"Packages": [],
"Parameters": [
{
"Id": "b4c7f413-9341-4602-b5f4-5d69365e6cff",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.AzureAccount",
"Label": "Azure Account",
"HelpText": "An Azure account with permission to both retrieve values from the Azure App Config store and publish to the App Function",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "AzureAccount"
}
},
{
"Id": "fcf6f1fd-1b3c-47d2-8037-802224c76452",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreName",
"Label": "Config Store Name",
"HelpText": "The name of the Azure App Configuration store. Provide this or the **Config store endpoint**.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "7d6b9332-9c13-42b1-83b5-a8e84fc593f0",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreEndpoint",
"Label": "Config Store Endpoint",
"HelpText": "The endpoint for the Azure App Configuration Store. Provide this or the **Config store name**.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "c25b6875-2007-4d55-97a1-7ec7b061b06b",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.RetrievalMethod",
"Label": "Retrieval Method",
"HelpText": "Choose how the step calls the az cli. Either:\n- `All`: Retrieve all configuration values in one call\n- `Individually`: Retrieve configuration values in multiple calls; one for each key specified in the **Key Names** parameter.\n\nDefault: `All`",
"DefaultValue": "all",
"DisplaySettings": {
"Octopus.ControlType": "Select",
"Octopus.SelectOptions": "all|All\nindividual|Individually"
}
},
{
"Id": "cf069635-3027-47a4-8965-d229c8e64afd",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.KeyNames",
"Label": "Key Names",
"HelpText": "Specify the names of the keys to be returned from Azure App Configuration in the format `KeyName | CustomSettingName` where:\n\n- `KeyName` is the key to retrieve. Wildcards are supported by adding `*` at the end of the key name.\n- `CustomSettingName` is the _optional_ name to set for the AppSetting value in the App Function. *If this value isn't specified, the original key will be used.*.\n\n**Note:** Multiple keys can be retrieved by entering each one on a new line. Note: Combining a wildcard search with custom setting names is not supported.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
}
},
{
"Id": "13007305-0fa2-468c-b7de-3c5317bd8611",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.Labels",
"Label": "Labels",
"HelpText": "Labels are an attribute on keys. Provide one or more labels in the format `label1,label2` to retrieve only selected keys tagged with those labels.\n\n**Note:** You can include both label values *and* specify key names if you want.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "a7e79ba3-5ea3-40ab-9759-aa281e3c02f9",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.SuppressWarnings",
"Label": "Suppress warnings",
"HelpText": "Suppress warnings from being written to the task log. For example, when a supplied key can't be found in the Azure App Configuration store.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "62d8f95f-8a57-4908-b789-c3ecabd7c6dd",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.TreatWarningsAsErrors",
"Label": "Treat Warnings as Errors",
"HelpText": "Treats warnings as errors. If enabled the **Suppress Warnings** parameter is ignored. ",
"DefaultValue": "True",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
},
{
"Id": "c8c1c14d-a515-47e7-b117-6a69644b78af",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.FunctionName",
"Label": "Azure Function App Name",
"HelpText": "The name of the Azure App function.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "07fcb750-13a1-4272-b6b6-a5cdd120a15f",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.ResourceGroup",
"Label": "Resource Group",
"HelpText": "The name of the resource group where the Function App is located.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "fbd1b5bf-e1ce-415c-b7db-9c9d49e9f8e3",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.Slot",
"Label": "Slot",
"HelpText": "\nThe name of the slot. Defaults to the production slot if not specified.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "21e9c8b3-50ce-4006-83a7-86d7803c31ee",
"Name": "AzFunction.SetAppSettings.FromAzAppConfig.AdditionalSettingsValues",
"Label": "Additional AppSettings",
"HelpText": "Specify the name and values of any **additional** settings to be applied to the Azure App Function in the format `KEY | VALUE` where:\n\n- `KEY` is the name of the app setting to add\n- `VALUE` is the value to be used. [Octopus variables](https://octopus.com/docs/projects/variables) can be used here.\n\n\n**Note:** Multiple settings can be added by entering each one on a new line. As a result, values that span multiple lines will result in an error.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"OctopusUseBundledTooling": "False",
"Octopus.Action.Script.ScriptBody": "$ErrorActionPreference = 'Stop'\n\n# KV Variables\n$global:AzureAppConfigStoreName = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreName\"]\n$global:AzureAppConfigStoreEndpoint = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.ConfigStoreEndpoint\"]\n$global:AzureAppConfigRetrievalMethod = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.RetrievalMethod\"]\n$ConfigStoreKeyNames = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.KeyNames\"]\n$global:ConfigStoreLabels = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.Labels\"]\n$global:SuppressWarnings = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.SuppressWarnings\"] -ieq \"True\"\n$global:TreatWarningsAsErrors = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.TreatWarningsAsErrors\"] -ieq \"True\"\n\n# Function Variables\n$FunctionName = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.FunctionName\"]\n$ResourceGroup = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.ResourceGroup\"]\n$AdditionalSettingsValues = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.AdditionalSettingsValues\"]\n$Slot = $OctopusParameters[\"AzFunction.SetAppSettings.FromAzAppConfig.Slot\"]\n\n# KV params validation\nif ([string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreName) -and [string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreEndpoint)) {\n throw \"Either parameter ConfigStoreName or ConfigStoreEndpoint not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($global:AzureAppConfigRetrievalMethod)) {\n throw \"Required parameter AzFunction.SetAppSettings.FromAzAppConfig.RetrievalMethod not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($ConfigStoreKeyNames) -and [string]::IsNullOrWhiteSpace($global:ConfigStoreLabels)) {\n throw \"Either AzFunction.SetAppSettings.FromAzAppConfig.KeyNames or AzFunction.SetAppSettings.FromAzAppConfig.Labels not specified\"\n}\n\n# Function params validation\nif ([string]::IsNullOrWhiteSpace($FunctionName)) {\n throw \"Required parameter AzureFunction.ConfigureAppSettings.FunctionName not specified\"\n}\n\nif ([string]::IsNullOrWhiteSpace($ResourceGroup)) {\n throw \"Required parameter AzureFunction.ConfigureAppSettings.ResourceGroup not specified\"\n}\n\n$RetrieveAllKeys = $global:AzureAppConfigRetrievalMethod -ieq \"all\"\n$global:ConfigStoreParameters = \"\"\nif (-not [string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreName)) {\n $global:ConfigStoreParameters += \" --name \"\"$global:AzureAppConfigStoreName\"\"\"\n}\nif (-not [string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreEndpoint)) {\n $global:ConfigStoreParameters += \" --endpoint \"\"$global:AzureAppConfigStoreEndpoint\"\"\"\n}\n\n### Helper functions\nfunction Test-ForAzCLI() {\n $oldPreference = $ErrorActionPreference\n $ErrorActionPreference = \"Stop\"\n try { \n if (Get-Command \"az\") {\n return $True\n }\n }\n catch { \n return $false\n }\n finally { \n $ErrorActionPreference = $oldPreference \n }\n}\n\n\nfunction Write-OctopusWarning(\n [string] $Message\n) {\n if ($global:TreatWarningsAsErrors) {\n throw \"Error: $Message\"\n }\n else {\n if ($global:SuppressWarnings -eq $False) {\n Write-Warning -Message $Message\n }\n else {\n Write-Verbose -Message $Message\n }\n }\n}\n\nfunction Save-AppSetting(\n [string]$settingName, \n [string]$settingValue) {\n\n $global:Settings += [PsCustomObject]@{name = $settingName; value = $settingValue; slotSetting = $false }\n}\n\nfunction Find-AzureAppConfigMatchesFromKey(\n [string]$KeyName,\n [bool]$IsWildCard,\n [string]$settingName,\n [PsCustomObject]$AppConfigValues) {\n\n if ($IsWildCard -eq $False) {\n Write-Verbose \"Finding exact match for: $keyName\"\n $matchingAppConfigKeys = $appConfigValues | Where-Object { $_.key -ieq $keyName }\n if ($null -eq $matchingAppConfigKeys -or $matchingAppConfigKeys.Count -eq 0) {\n Write-OctopusWarning \"Unable to find a matching key in Azure App Config for: $keyName\"\n }\n else {\n\n if ($matchingAppConfigKeys.Count -gt 1) {\n Write-OctopusWarning \"Found multiple matching keys ($($matchingAppConfigKeys.Count)) in Azure App Config for: $keyName. This is usually due to multiple values with labels\"\n\n foreach ($matchingAppConfigKey in $matchingAppConfigKeys) {\n Write-Verbose \"Found match for $keyName $(if(![string]::IsNullOrWhiteSpace($matchingAppConfigKey.content_type)) {\"($($matchingAppConfigKey.content_type))\"})\"\n $settingValue = $matchingAppConfigKey.value\n \n if ([string]::IsNullOrWhiteSpace($settingName)) {\n $settingName = $keyName.Trim()\n }\n if (![string]::IsNullOrWhiteSpace($matchingAppConfigKey.label)) {\n $settingName = \"$($keyName.Trim())-$($matchingAppConfigKey.label)\"\n Write-Verbose \"Appending label to setting name to avoid duplicate setting: $settingName\"\n }\n \n Save-AppSetting -settingName $settingName -settingValue $settingValue\n }\n } \n else {\n $matchingAppConfigKey = $matchingAppConfigKeys | Select-Object -First 1\n Write-Verbose \"Found match for $keyName $(if(![string]::IsNullOrWhiteSpace($matchingAppConfigKey.content_type)) {\"($($matchingAppConfigKey.content_type))\"})\"\n $settingValue = $matchingAppConfigKey.value\n \n if ([string]::IsNullOrWhiteSpace($settingName)) {\n $settingName = $keyName.Trim()\n }\n \n Save-AppSetting -settingName $settingName -settingValue $settingValue\n }\n }\n }\n else {\n Write-Verbose \"Finding wildcard match for: $keyName\"\n $matchingAppConfigKeys = @($appConfigValues | Where-Object { $_.key -ilike $keyName })\n if ($matchingAppConfigKeys.Count -eq 0) {\n Write-OctopusWarning \"Unable to find any matching keys in Azure App Config for wildcard: $keyName\"\n }\n else {\n foreach ($match in $matchingAppConfigKeys) {\n # Have to explicitly set settings as they are wildcard matches\n $settingName = $match.key\n $settingValue = $match.value\n Write-Verbose \"Found wildcard match '$settingName' $(if(![string]::IsNullOrWhiteSpace($matchingAppConfigKey.content_type)) {\"($($matchingAppConfigKey.content_type))\"})\"\n Save-AppSetting -settingName $settingName -settingValue $settingValue\n }\n }\n }\n}\n\nfunction Find-AzureAppConfigMatchesFromLabels() {\n \n Write-Verbose \"Retrieving values matching labels: $global:ConfigStoreLabels\"\n $command = \"az appconfig kv list $global:ConfigStoreParameters --label \"\"$global:ConfigStoreLabels\"\" --auth-mode login\"\n \n Write-Verbose \"Invoking expression: $command\"\n $appConfigResponse = Invoke-Expression -Command $command\n $ExitCode = $LastExitCode\n Write-Verbose \"az exit code: $ExitCode\"\n if ($ExitCode -ne 0) {\n throw \"Error retrieving appsettings. ExitCode: $ExitCode\"\n }\n\n if ([string]::IsNullOrWhiteSpace($appConfigResponse)) {\n Write-OctopusWarning \"Null or empty response received from Azure App Configuration service\"\n }\n else {\n $appConfigValues = $appConfigResponse | ConvertFrom-Json\n if ($appConfigValues.Count -eq 0) {\n Write-OctopusWarning \"Unable to find any matching keys in Azure App Config for labels: $global:ConfigStoreLabels\"\n }\n else {\n Write-Verbose \"Finding match(es) for labels: $global:ConfigStoreLabels\"\n foreach ($appConfigValue in $appConfigValues) {\n # Have to explicitly set setting Name here as its a match based on label alone\n $settingName = $appConfigValue.key\n Write-Verbose \"Found label match '$($appConfigValue.key)' $(if(![string]::IsNullOrWhiteSpace($appConfigValue.content_type)) {\"($($appConfigValue.content_type))\"})\"\n if (![string]::IsNullOrWhiteSpace($appConfigValue.label)) {\n $settingName = \"$($settingName)-$($appConfigValue.label)\"\n Write-Verbose \"Appending label to setting to avoid duplicate name: $settingName\"\n }\n $settingValue = $appConfigValue.value\n \n Save-AppSetting -settingName $settingName -settingValue $settingValue\n }\n }\n }\n}\n\n# Check if Az cli is installed.\n$azCliAvailable = Test-ForAzCLI\nif ($azCliAvailable -eq $False) {\n throw \"Cannot find the Azure CLI (az) on the machine. This must be available to continue.\"\t\n}\n\n# Begin KV Retrieval\n$Keys = @()\n$global:Settings = @()\n\n# Extract key names+optional custom setting name\n@(($ConfigStoreKeyNames -Split \"`n\").Trim()) | ForEach-Object {\n if (![string]::IsNullOrWhiteSpace($_)) {\n Write-Verbose \"Working on: '$_'\"\n $keyDefinition = ($_ -Split \"\\|\")\n $keyName = $keyDefinition[0].Trim()\n $KeyIsWildcard = $keyName.EndsWith(\"*\")\n $settingName = $null\n if ($keyDefinition.Count -gt 1) {\n if ($KeyIsWildcard) {\n throw \"Key definition: '$_' evaluated as a wildcard with a custom setting name. This is not supported.\"\n }\n $settingName = $keyDefinition[1].Trim()\n }\n\n if ([string]::IsNullOrWhiteSpace($keyName)) {\n throw \"Unable to establish key name from: '$_'\"\n }\n\n $key = [PsCustomObject]@{\n KeyName = $keyName\n KeyIsWildcard = $KeyIsWildcard\n SettingName = if (![string]::IsNullOrWhiteSpace($settingName)) { $settingName } else { \"\" }\n }\n $Keys += $key\n }\n}\n\n$LabelsArray = $global:ConfigStoreLabels -Split \",\" | Where-Object { [string]::IsNullOrWhiteSpace($_) -eq $False }\n\nWrite-Verbose \"Azure AppConfig Retrieval Method: $global:AzureAppConfigRetrievalMethod\"\nif (![string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreName)) {\n Write-Verbose \"Azure AppConfig Store Name: $global:AzureAppConfigStoreName\"\n}\nif (![string]::IsNullOrWhiteSpace($global:AzureAppConfigStoreEndpoint)) {\n Write-Verbose \"Azure AppConfig Store Endpoint: $global:AzureAppConfigStoreEndpoint\"\n}\nWrite-Verbose \"Suppress warnings: $global:SuppressWarnings\"\nWrite-Verbose \"Treat warnings as errors: $global:TreatWarningsAsErrors\"\nWrite-Verbose \"Keys to retrieve: $($Keys.Count)\"\nWrite-Verbose \"Labels to retrieve: $($LabelsArray.Count)\"\n\n$appConfigResponse = $null\n\n# Retrieving all keys should be more performant, but may have a larger payload response.\nif ($RetrieveAllKeys) {\n \n if ($Keys.Count -gt 0) {\n Write-Host \"Retrieving ALL config values from store\"\n $command = \"az appconfig kv list $global:ConfigStoreParameters --all --auth-mode login\"\n \n if (![string]::IsNullOrWhiteSpace($global:ConfigStoreLabels)) {\n $command += \" --label \"\"$global:ConfigStoreLabels\"\" \"\n }\n Write-Verbose \"Invoking expression: $command\"\n $appConfigResponse = Invoke-Expression -Command $command\n $ExitCode = $LastExitCode\n Write-Verbose \"az exit code: $ExitCode\"\n if ($ExitCode -ne 0) {\n throw \"Error retrieving appsettings. ExitCode: $ExitCode\"\n }\n \n if ([string]::IsNullOrWhiteSpace($appConfigResponse)) {\n Write-OctopusWarning \"Null or empty response received from Azure App Configuration service\"\n }\n else {\n $appConfigValues = $appConfigResponse | ConvertFrom-Json\n }\n\n foreach ($key in $Keys) {\n $keyName = $key.KeyName\n $KeyIsWildcard = $key.KeyIsWildcard\n $SettingName = $key.SettingName\n \n Find-AzureAppConfigMatchesFromKey -KeyName $keyName -IsWildcard $KeyIsWildcard -SettingName $SettingName -AppConfigValues $appConfigValues\n }\n }\n # Possible that ONLY labels have been provided\n elseif ($LabelsArray.Count -gt 0) {\n Find-AzureAppConfigMatchesFromLabels \n }\n}\n# Loop through and get keys based on the supplied names\nelse {\n \n Write-Host \"Retrieving keys based on supplied names...\"\n if ($Keys.Count -gt 0) {\n foreach ($key in $Keys) {\n $keyName = $key.KeyName\n $KeyIsWildcard = $key.KeyIsWildcard\n $settingName = $key.SettingName\n\n if ([string]::IsNullOrWhiteSpace($settingName)) {\n $settingName = \"$($keyName.Trim())\"\n }\n\n Write-Verbose \"Retrieving values matching key: $keyName from store\"\n $command = \"az appconfig kv list $global:ConfigStoreParameters --key \"\"$keyName\"\" --auth-mode login\"\n \n if (![string]::IsNullOrWhiteSpace($global:ConfigStoreLabels)) {\n $command += \" --label \"\"$global:ConfigStoreLabels\"\" \"\n }\n Write-Verbose \"Invoking expression: $command\"\n\n $appConfigResponse = Invoke-Expression -Command $command\n $ExitCode = $LastExitCode\n Write-Verbose \"az exit code: $ExitCode\"\n if ($ExitCode -ne 0) {\n throw \"Error retrieving appsettings. ExitCode: $ExitCode\"\n }\n\n if ([string]::IsNullOrWhiteSpace($appConfigResponse)) {\n Write-OctopusWarning \"Null or empty response received from Azure App Configuration service\"\n }\n else {\n $appConfigValues = $appConfigResponse | ConvertFrom-Json\n if ($appConfigValues.Count -eq 0) {\n Write-OctopusWarning \"Unable to find a matching key in Azure App Config for: $keyName\"\n }\n else {\n Write-Verbose \"Finding match(es) for: $keyName\"\n Find-AzureAppConfigMatchesFromKey -KeyName $keyName -IsWildcard $KeyIsWildcard -SettingName $settingName -AppConfigValues $appConfigValues\n }\n }\n }\n }\n}\n# End KV Retrieval\n\n# Begin AZ Function set\n\n$AdditionalSettings = @()\n#$SlotSettings = @()\n\n# Extract additional settings values\nif (-not [string]::IsNullOrWhiteSpace($AdditionalSettingsValues)) {\n @(($AdditionalSettingsValues -Split \"`n\").Trim()) | ForEach-Object {\n if (![string]::IsNullOrWhiteSpace($_)) {\n Write-Verbose \"Working on: '$_'\"\n if (-not $_.Contains(\"|\")) {\n throw \"Setting '$_' doesnt contain the '|' delimiter. Multi-line values aren't supported.\"\n }\n $settingDefinition = ($_ -Split \"\\|\")\n $settingName = $settingDefinition[0].Trim()\n $settingValue = \"\"\n if ($settingDefinition.Count -gt 1) {\n $settingValue = $settingDefinition[1].Trim()\n }\n if ([string]::IsNullOrWhiteSpace($settingName)) {\n throw \"Unable to establish additional setting name from: '$_'\"\n }\n $setting = [PsCustomObject]@{\n name = $settingName\n value = $settingValue\n slotSetting = $false\n }\n $AdditionalSettings += $setting\n }\n }\n}\n\n\nif ($Settings.Count -gt 0 -or $AdditionalSettings.Count -gt 0) {\n Write-Host \"Settings found to publish to App Function: $FunctionName\"\n\n Write-Verbose \"Function Name: $FunctionName\"\n Write-Verbose \"Resource Group: $ResourceGroup\"\n Write-Verbose \"Slot: $Slot\"\n Write-Verbose \"Settings: $($Settings.Count)\"\n Write-Verbose \"Additional Settings: $($AdditionalSettings.Count)\"\n if ($AdditionalSettings.Count -gt 0) {\n Write-Verbose \"Combining additional settings with settings retrieved from Azure App Config\"\n $Settings = $Settings + $AdditionalSettings\n }\n\n $settingsFile = $null\n\n try {\n\n $command = \"az functionapp config appsettings set --name=\"\"$Functionname\"\" --resource-group \"\"$ResourceGroup\"\" \"\n if (-not([string]::IsNullOrWhiteSpace($Slot))) {\n $command += \" --slot \"\"$Slot\"\" \"\n }\n\n if ($Settings.Count -ge 1) {\n $settingsFile = [System.IO.Path]::GetRandomFileName()\n $ConvertToJsonParameters = @{}\n if ($PSVersionTable.PSVersion.Major -ge 6) {\n $ConvertToJsonParameters.Add(\"AsArray\", $True)\n }\n $Settings | ConvertTo-Json @ConvertToJsonParameters | Set-Content -Path $settingsFile\n $command += \" --settings '@$settingsFile'\"\n }\n\n Write-Verbose \"Invoking expression: $command\"\n Write-Host \"##octopus[stderr-progress]\"\n $settingsUpdateResponse = Invoke-Expression -Command $command\n $ExitCode = $LastExitCode\n Write-Verbose \"FunctionApp update ExitCode: $ExitCode\"\n if ($ExitCode -ne 0) {\n throw \"Error configuring appsettings for function app '$FunctionName'. ExitCode: $ExitCode\"\n }\n Write-Host \"##octopus[stderr-default]\"\n if ($null -ne $settingsUpdateResponse) {\n Write-Host \"Update of function '$FunctionName' was successful\"\n try {\n $functionSettings = $settingsUpdateResponse | ConvertFrom-Json\n if ($null -ne $functionSettings) {\n $settingsCount = @($functionSettings | Where-Object { $_.slotSetting -eq $False }).Count\n $slotSettingsCount = @($functionSettings | Where-Object { $_.slotSetting -eq $True }).Count\n Write-Verbose \"Function '$FunctionName' has $settingsCount setting(s) and $slotSettingsCount slot setting(s).\"\n }\n }\n catch {}\n }\n \n }\n catch { throw }\n finally {\n if (-not([string]::IsNullOrWhiteSpace($settingsFile))) {\n Write-Verbose \"Removing temporary settings file $settingsFile\"\n Remove-Item -Path $settingsFile -Force -ErrorAction Ignore\n }\n if (-not([string]::IsNullOrWhiteSpace($slotSettingsFile))) {\n Write-Verbose \"Removing temporary slot settings file $slotSettingsFile\"\n Remove-Item -Path $slotSettingsFile -Force -ErrorAction Ignore\n }\n }\n}\nelse {\n Write-Host \"No settings found to publish to the Azure App function\"\n}",
"Octopus.Action.Azure.AccountId": "#{AzFunction.SetAppSettings.FromAzAppConfig.AzureAccount}"
},
"Category": "Azure",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/azure-function-set-appsettings-from-azconfig.json",
"Website": "/step-templates/67fcc93c-509c-4c13-bc24-645eff53c5c2",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////AHjXf7vrv931QJrh7/f8EIDaIIncMJHfYKvmz+b3n8zw3+76j8Ttr9XycLPpUKLkkKvYFAAABGZJREFUeNrsnNmCqjoQRc1MEiD8/9cer7Yt2KBJZQC8ez07sKlKTQlcLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzoUSnt8YxXlFuGHSbIaxvj+fip4btkLn1blkWLaF5v03yLhLOYlVuGYfMOMZzNGxCOzhjTJqFkXnjq3Dr1yyvPI3hGl3Ih3zzHHNKudRstRhX5O58vIcShY67Gq6EPIESlzUWvazaGAOGbvU7ArDu/g8M4o8opDZWvbvPzlL/MMBE8jT9T9W7PbAJlHPTBFRf9yVTEcs63msXz2UHLSgf650G/d5t+wjbxxB2UCMqGrk8/LFSD7uJMeNt5bcJCyQZyAe5Fo9KYfWS2flQrr4b4tpuzaeWjYs49rt9LHf9uZD7+VbyVi9EBNrjYjuq2sxQOrl+p+HuBVu45qvqfq691ttYFQ5KyKbyJgaIY/NGxrlWZwlwGvmvu1oY3PuAv0niTq6tZ78jk//9uc1r1r4lQki7y7sp2Tu4V1y2iLoqFTqi1lIGcpFiebrZNZ1dOkF0cCIlO8jQ47nCkam9Lilz9GhDF1I6XGLzfnhwDIIZVfI7+8SSgfHsijqXENOGJF5QorG4EcW0OrScqX/dDrXpr70Ut/BII+1OfECPuYz/NWxYmgrCsUskxPvyhgmrw+WGZ6lGTuOlIyCYWTFyWjpM5KIZRUIOwjRNYRQ6tZF9BXtk8hWAHPtLNJ727Fq0JSkC1FDRRF0Jalj0d5qVh2KEpM2TuSsCYTCT6ZkdmFYI9LrYp5QayWbo6NXlZwcRD/61pth5Fq5EX423QQxNjhqWvvklkljOLkYjrmphXPZOJOk6Pg7HKMsrtQKcowzZoK3rx1ZUelGMdQA/HaKkjAt2RgqpZeYqbNbH7Hp2ct4nqfSPOfe0ftiSTZJydOV6rG5bQbyLK+nRuCC0343PzDgiOXyQA5c14BTZi98uR/5KJ1SnatLdoO50WWBQZPTq0VgsklU3h932actuo17ayrHrb/3ykiegd3KbqF2wbV6RrlsJ07yLcpsWFTul9RyK6ZScr+tk7oNrFj0o7HQUlj4EiEvJ6rPLKSmlMZCrksl1OnLaRkxc+/HB1naMhNtT/6yM2bDs6azCRHrM3aVPN7aW8irD/10B8njpAMcsl8okXcdKrl4sPsLmQVy/Sj90ucPRc/d/Bxxj+dXSpCayen32D+hLi16MsIV8gfCXrYp6ySsiJKRUF0XXiLpVbFU+fNv4r7mOwhFsX4ZdwpSi1DYs2jb6ebZ9788cblTzMrYhu7sf/17IFdtuviJ2ioHA6pMHkoH4CLUeMBU7iGkxuM/YgcdderF9ibRdc7O982F1HpYhjfWUe+x5a6pjop9iNLfoePvlsdZdTSMwfxSmTY20Q0eHnUNzga1edeNmmqbg18aMVR1L9vwSXHF9TfIWBxpKLs2hj3eQeBC0USvp2HHF3eIkRdhFOd6ER8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/I/4J8AAo/80BciBec4AAAAASUVORK5CYII=",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Thursday, November 30, 2023