1

I have a powershell script, that take my variable and deliver it to the my helm upgrade command

param
(   
    [Parameter(Mandatory = $false)]
    $HELM_SET
)
    helm upgrade --install myrelease -n dev my_service.tgz $HELM_SET 

My HELM_SET var contains:
--set config.vali=x --set config.spring=v1

But helm said after upgrade: Error: unknown flag: --set config.vali helm.go:88: [debug] unknown flag: --set config.vali

if i'm add "--set" into helm upgrade --install myrelease -n dev my_service.tgz --set $HELM_SET and my HELM_SET var now contains: config.vali=x --set config.spring=v1

after upgrade i receive that my config:vali var is x --set config.spring=v1

Can someone explain me what i'm doing wrong?

1
  • How are you executing this script? Is it a function or just ps1 file with a param(...) block? If it's a external script, are you executing it from powershell or from cmd? Do you run it like this: .\script.ps1 --set config.vali=x --set config.spring=v1 ? Commented Nov 24, 2021 at 23:17

1 Answer 1

1

If you're passing $HELM_SET as a single string encoding multiple arguments, you cannot pass it as-is to a command.

Instead, you'll need to parse this string into an array of individual arguments.

In the simplest case, using the unary form of the -split operator, which splits the string into an array of tokens by whitespace:

helm upgrade --install myrelease -n dev my_service.tgz (-split $HELM_SET)

However, if your arguments include quoted strings (e.g. --set config.spring="v 1"), more work is needed, because the quoted strings must be recognize as such, so as not to break them into multiple tokens by their embedded whitespace:

# Note: Use of Invoke-Expression is safe here, but should generally be avoided.
$passThruArgs = (Invoke-Expression ('Write-Output -- ' + $HELM_SET -replace '\$', "`0")) -replace "`0", '$$'

helm upgrade --install myrelease -n dev my_service.tgz $passThruArgs

See this answer for an explanation of this technique.


If you control the invocation of your script, a simpler solution is available:

As Santiago Squarzon points out, you can use the ValueFromRemainingArguments property of a parameter declaration to collect all arguments (that aren't bound to other parameters):

param
(   
    [Parameter(ValueFromRemainingArguments)]
    $__passThruArgs # Choose an exotic name that won't be used in the actual arguments
)

helm upgrade --install myrelease -n dev my_service.tgz $__passThruArgs

Instead of passing the pass-through arguments as a single string, you would then pass them as individual arguments:

./yourScript.ps1 --set config.vali=x --set config.spring=v1
Sign up to request clarification or add additional context in comments.

4 Comments

I'm wondering, wouldn't param([parameter(ValueFromRemainingArguments)][string]$HELM_SET) work in this case?
With a param block like above and then as an example bash -c $HELM_SET if I call the script like .\script.ps1 sudo apt update && sudo apt upgrade it works just fine without the need for -split or passing the argument as a string using quotes.
Excellent point re ValueFromRemainingArguments, @SantiagoSquarzon - please see my update. As for bash -c: you're passing a single string to another scripting engine, and it then interprets that string as source code. It is equivalent to calling eval on a string from within bash / calling Invoke-Expression on a string from within PowerShell.
Makes sense, it also explains why I must type constraint the argument to [string] using this method for bash -c but I couldn't think of a binary to test this on. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.