az functionapp config appsettings set Errors When Used in PowerShell with Multiple Settings
See original GitHub issueDescribe the bug
I have been trying to troubleshoot why I am unable to use the documented --settings
switch with multiple space separated Key=Value
pairs Documentation in a PowerShell script I have for provisioning. In my production script I end up having all of the secrets roll into the first secret which I am trying to reproduce.
I have created a small test script to try to troubleshoot the issue and was able to get a slightly different error message.
Command Name
az functionapp config appsettings set
Errors:
The command failed with an unexpected error. Here is the traceback:
not enough values to unpack (expected 2, got 1)
Traceback (most recent call last):
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/util.py", line 557, in shell_safe_json_parse
File "json\__init__.py", line 359, in loads
File "json\decoder.py", line 337, in decode
File "json\decoder.py", line 355, in raw_decode
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/appservice/custom.py", line 392, in update_app_settings
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/util.py", line 583, in shell_safe_json_parse
azure.cli.core.azclierror.InvalidArgumentValueError: Failed to parse string as JSON:
at
Error detail: Expecting value: line 1 column 1 (char 0)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\knack/cli.py", line 233, in invoke
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 663, in execute
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 726, in _run_jobs_serially
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 718, in _run_job
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/appservice/commands.py", line 40, in _ex_handler
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 697, in _run_job
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/__init__.py", line 333, in __call__
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/core/commands/command_operation.py", line 121, in handler
File "D:\a\1\s\build_scripts\windows\artifacts\cli\Lib\site-packages\azure/cli/command_modules/appservice/custom.py", line 403, in update_app_settings
ValueError: not enough values to unpack (expected 2, got 1)
To Reproduce:
Steps to reproduce the behavior. Note that argument values have been redacted, as they may contain sensitive information.
az functionapp config appsettings set --name {} --resource-group {} --settings {} {} {} {} {} {} {}
The command is being generated from this PowerShell Script (I have redacted any private information):
$appSettingsToUpdate = [System.Collections.Generic.Dictionary[string, string]]::new()
$appSettingsToUpdate.Add("Setting1", "Set at $(Get-Date)")
$appSettingsToUpdate.Add("Setting2", "Set at $(Get-Date)")
[System.Text.StringBuilder]$settingsString = [System.Text.StringBuilder]::new()
foreach ($appSettingToUpdate in $appSettingsToUpdate.GetEnumerator()) {
$settingsString.Append("""$($appSettingToUpdate.Key)=$($appSettingToUpdate.Value)"" ") | Out-Null
}
$expandedSettingsString = $settingsString.ToString()
# Set the new settings; This will restart the function app
az functionapp config appsettings set --name {REDACTED} --resource-group {REDACTED} --settings $expandedSettingsString | Out-Null
Expected Behavior
I would expect this to work. This should be equivalent to:
az functionapp config appsettings set --name {REDACTED} --resource-group {REDACTED} --settings "Setting1=Set at 09/16/2022 09:21:42" "Setting2=Set at 09/16/2022 09:21:42"
Which does work when manually run through the command line
Workaround
I suspect that there is probably some weird behavior with PowerShell and the way that this parses commands. I am going to attempt a work around by just providing the settings as a JSON file. However this is not documented to work this way for functionapp
but is documented to work this way for webapp
(See Documentation) I suspect that this will work even if not documented to do so (that should be fixed).
Environment Summary
Windows-10-10.0.19044-SP0
Python 3.10.5
Installer: MSI
azure-cli 2.40.0
Extensions:
azure-devops 0.25.0
Dependencies:
msal 1.18.0b1
azure-mgmt-resource 21.1.0b1
Additional Context
Issue Analytics
- State:
- Created a year ago
- Comments:7 (3 by maintainers)
Top GitHub Comments
@jiasli BINGO! Thank you for linking the PowerShell issue that is what I was looking for as I felt the original code met the requirements of a space separated “Key=Value” pair. It is PowerShell’s mishandling of the double quotes (in versions prior to 7.3) that was the root cause of this issue.
The intent of this line:
Was to produce a string that looked like
"Setting1=Set at 2022/09/19" "Setting2=Set at 2022/09/19"
however as per the linked PowerShell issue this was munged. It is helpful to know that the Azure CLI provides this output:cli.knack.cli: Command arguments: ['functionapp', 'config', 'appsettings', 'set', '--name', 'REDACTED', '--resource-group', 'REDACTED', '--settings', 'Setting1=Set at 09/19/2022 11:28:21', 'Setting2=Set at 09/19/2022 11:28:21', '--debug']
The fact that
$expandedSettingsString
gets torn apart is due to PowerShell issue https://github.com/PowerShell/PowerShell/issues/1995:I guess it’s because when calling native exe, PowerShell passes
$expandedSettingsString
asThis is fixed in PowerShell 7.3:
The correct way to pass multiple arguments is to use