问题
The following command works fine on Ubuntu bash:
kubectl patch deployment wapi-backend-d1 --patch '{"spec": {"template": {"metadata": {"labels": {"date": "test"}}}}}'
The same command does not work in Windows Powershell Console (ISE).
The error is:
kubectl : Error from server (BadRequest): invalid character 's' looking for beginning of object key string
At line:1 char:1
+ kubectl patch deployment wapi-backend-d1 --patch '{"spec": {"template ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Error from serv...ject key string:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
The powershell console version is:
PS > $PSVersionTable
Name Value
---- -----
PSVersion 5.1.14409.1005
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.14409.1005
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
I have tried the command with a different patched value too as I saw somebody write that patch may fail if it is already applied.
The path /spec/template/metadata/labels/date indeed exists in the deployment's yaml, so that isn't a problem either.
I presume that it might have something to do with kubectl working differently in Powershell in relation to quotes, but could not find a way to make it work.
I have tried
kubectl patch deployment wapi-backend-d1 --patch "{\"spec\": {\"template\": {\"metadata\": {\"labels\": {\"date\": \"test123\"}}}}}"
But that results in
Error from server (NotFound): deployments.extensions "spec\\: {\\template\\: {\\metadata\\: {\\labels\\: {\\date\\: \\test123\\}}}}}" not found
What should be the command on Powershell?
回答1:
For detailed and very useful background, see the answer by mklement0
After much frustration, I have decided to list all variants of quote escaping that I've tried, and came up with one more, which suddenly worked! So, sharing it here:
kubectl patch deployment wapi-backend-d1 --patch '{\"spec\": {\"template\": {\"metadata\": {\"labels\": {\"date\": \"test123\"}}}}}'
This is how to use kubectl patch with Powershell
Also, of note: I was actually trying to patch it with a timestamp to trigger a rolling update without changing tags of container images (so set image would not help me).
When you try to put your JSON into a variable and then call kubectl patch with a variable, you get into trouble with escaping again. This is what I ended up with:
$patchRequest = @{
spec = @{
template = @{
metadata = @{
labels = @{
date = ((((Get-Date -Format o)).replace(':','-').replace('+','_')))
}
}
}
}
}
$patchJson = ((ConvertTo-Json -InputObject $patchRequest -Compress -Depth 10))
$patchJson = $patchJson.replace('"','\"')
kubectl patch deployment wapi-backend-d1 --patch $patchJson
回答2:
You've found the right solution in your own answer, but let me try to break it down conceptually:
Embedding " (double quotes) in string arguments passed to external programs:
(a) First - sensibly and unavoidably - you need to satisfy PowerShell's syntax requirements with respect to embedding
"chars. in quoted strings.(b) Then - and this step shouldn't be necessary - you need to
\-escape embedded"chars. that you want external programs to see.- This is a longstanding, irksome bug that is unlikely to be fixed, however, as long as backward compatibility must be maintained; see this GitHub issue.
Re (a), you have the following options:
'...'-quoting (single-quoting), inside of which you can use"as-is:'{ "spec": "none" }'- Everything inside
'...'is taken literally - no expansion (interpolation) takes place.
"..."-quoting (double-quoting), inside of which you can use`"or""to embed"chars:"{ `"spec`": `"none`" }"-`is PowerShell's general escape char."{ ""spec"": ""none"" }"-"-specific escaping (doubling)- The content of
"..."is subject to expansion (interpolation), meaning that you can reference variables ($var) or subexpressions ($(1 + 2)) inside such strings, which PowerShell replaces with their values - see this answer for more about PowerShell's expandable strings.
If you're passing such a string to other PowerShell commands (cmdlets, functions, or scripts), no further action is needed; e.g.:
PS> Write-Output '3" of rain'
3" of rain
Re (b) - i.e. to pass such strings to external programs - you additionally need to \-escape the embedded " chars.:
Applying manual escaping to the examples above:
'{ \"spec\": \"none\" }'"{ \`"spec\`": \`"none\`" }""{ \""spec\"": \""none\"" }"
Applying the escaping programmatically to a preexisting string:
$str = '3" of rain'; $escapedStr = $str -replace '"', '\"'
That is, for an external program to ultimately see literal value
3" of rain, you must pass literal value3\" of rainfrom PowerShell. This\-escaping is something that PowerShell, as a shell, should do automatically behind the scenes, but currently doesn't.There's an additional bug in Windows PowerShell - since fixed in PowerShell Core - that mishandles strings with unbalanced embedded
"chars. if a"is part of the first word:- E.g., the above techniques do NOT work with literal values such as
3" of rain; that is, escaping this as'3\" of rain'does not work as expected - instead, you must use the following monstrosity:`"3\`" of rain`", which is technically a series of separate, unquoted arguments, which means that (a) multiple spaces between the words of the strings aren't supported (they are collapsed to a single space) and (b) PowerShell metacharacters such as& < > $ & | @ {must be individually`-escaped. - Note that the bug surfaces only if the
"is part of the first word in the value, and only if that first word is not preceded by whitespace (though arguments with leading whitespace are rarely useful); e.g.,'3 \" of rain'would again work, because the unbalanced"is not part of the first word.
- E.g., the above techniques do NOT work with literal values such as
E.g.:
# Using choice.exe as a sample external program to pass a string to.
# choice.exe echoes the string it receives via /m as the prompt message.
PS> choice /m '{ \"spec\": \"none\" }' /d Y /t 0
{ "spec": "none" } [Y,N]?Y
来源:https://stackoverflow.com/questions/55602559/kubectl-patch-works-on-linux-bash-but-not-in-windows-powershell-ise