PSArm icon indicating copy to clipboard operation
PSArm copied to clipboard

Come up with a better concat/string interpolation strategy

Open rjmholt opened this issue 3 years ago • 4 comments

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:

  1. Use AST rewriting to rewrite string literals into calls to concat
  2. 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.

rjmholt avatar Apr 02 '21 21:04 rjmholt

Can PSPropertyExpression helps?

iSazonov avatar Apr 03 '21 03:04 iSazonov

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

rdbartram avatar Apr 05 '21 20:04 rdbartram

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

rdbartram avatar Apr 05 '21 20:04 rdbartram

See https://github.com/PowerShell/PSArm/discussions/147

rjmholt avatar Apr 05 '21 20:04 rjmholt