PSArm
PSArm copied to clipboard
Come up with a better concat/string interpolation strategy
Today in PSArm, you must use the concat
function to make string concatenation work at template deployment time.
Ordinary PowerShell string manipulation methods work if all your inputs are string literals:
$adminUsername = 'me'
Output ssh -Type string -Value "ssh $adminUsername"
Will render the output correctly as ssh me
.
But when using ARM operations, this starts to not work:
Arm {
param([ArmParameter[string]]$adminUsername)
Output ssh -Type string -Value "ssh $adminUsername"
}
Renders something like ssh [parameters('adminUsername')]
(it doesn't actually today, but it could easily).
Moreover, we often need to embed non-variable expressions in the interpolated strings, for example:
https://github.com/PowerShell/PSArm/blob/ccbfa8a9182a10872567472b61303c35aa44bff4/examples/linux-vm/linux-vm.psarm.ps1#L192
If we use a PowerShell string interpolation there:
"ssh${adminUsername}@$(reference $publicIPAddressName).dnsSettings.fqdn)"
We get something like:
ssh[parameters('adminUsername')]@[reference('myPublicIP').dnsSettings.fqdn]
which is completely unlike the required:
[concat('ssh', parameters('adminUsername'), '@', reference('myPublicIP').dnsSettings.fqdn)]
Some proposals so far:
- Use AST rewriting to rewrite string literals into calls to
concat
- Use a provider to turn PSArm string literals into provider paths and manipulate them after the fact
(1) carries the usual risk with AST rewriting that things will work in the case we imagine and go very bad in the other cases. Combining strings with +
or any command that operates on a string will go badly. Additionally, rewriting the AST is something that the PowerShell runtime sometimes refuses to allow because of optimisations in the variable table. However, this functionality would work for all string literals.
(2) requires more research, but my main concerns with it currently are that ultimately the string will be expanded as the outer path and require us to invent some intermediate string syntax for our provider parser to parse to make things work (and we still require users to specify arm:
in front of all strings). We also can't embed non-variable expressions in the provider. However, as we discuss this more, those concerns might not apply or be possible to work around.
Can PSPropertyExpression helps?
I did think about this the other day when testing out a couple configs. The initial thought is to go there I.e expect that string interpolation works, but after thinking about it, I’m not convinced it should implicitly. Explicitly marking concat denotes to me that the string is calculated at deploy time and not at build time. Just my 2c
Was of explictly defining could be
- manually writing out
- Method call I.e $variable.ToArmPath()
- Class implicit conversion [armpath]$variable
the last option seems most powershelly somehow like when you use [ref]. But I think I prefer the method call
See https://github.com/PowerShell/PSArm/discussions/147