【问题标题】:'kubectl patch' works on Linux Bash but not in Windows Powershell ISE“kubectl patch”适用于 Linux Bash,但不适用于 Windows Powershell ISE
【发布时间】:2019-08-31 07:44:19
【问题描述】:

以下命令在 Ubuntu bash 上运行良好:

kubectl patch deployment wapi-backend-d1 --patch '{"spec": {"template": {"metadata": {"labels": {"date": "test"}}}}}'

同一命令在 Windows Powershell 控制台 (ISE) 中不起作用。

错误是:

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

powershell控制台版本为:

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            

我也尝试过使用不同的补丁值的命令,因为我看到有人写道,如果补丁已经应用,它可能会失败。

路径 /spec/template/metadata/labels/date 确实存在于部署的 yaml 中,所以这也不是问题。

我认为这可能与 kubectl 在 Powershell 中与引号有关的工作方式不同有关,但找不到使其工作的方法。

我试过了

kubectl patch deployment wapi-backend-d1 --patch "{\"spec\": {\"template\": {\"metadata\": {\"labels\": {\"date\": \"test123\"}}}}}"

但这会导致

Error from server (NotFound): deployments.extensions "spec\\: {\\template\\: {\\metadata\\: {\\labels\\: {\\date\\: \\test123\\}}}}}" not found

Powershell 上的命令应该是什么?

【问题讨论】:

  • 你能从文件中获取 json 吗?

标签: powershell syntax parameter-passing kubectl quoting


【解决方案1】:

有关详细且非常有用的背景,请参阅answer by mklement0

在经历了很多挫折之后,我决定列出我尝试过的所有引用转义变体,并想出了另外一种,突然奏效了! 所以,在这里分享:

kubectl patch deployment wapi-backend-d1 --patch '{\"spec\": {\"template\": {\"metadata\": {\"labels\": {\"date\": \"test123\"}}}}}'

这是如何在 Powershell 中使用 kubectl 补丁

另外,值得注意的是:我实际上是在尝试使用时间戳对其进行修补以触发滚动更新而不更改容器图像的标签(因此设置图像对我没有帮助)。

当您尝试将 JSON 放入变量中,然后使用变量调用 kubectl patch 时,您会再次遇到转义问题。这就是我最终得到的结果:

$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】:

    您在 your own answer 中找到了正确的解决方案,但让我尝试从概念上分解它:

    在传递给外部程序的字符串参数中嵌入"(双引号):

    • (a) 首先 - 明智且不可避免 - 您需要满足 PowerShell 关于嵌入 " 字符的语法要求。在带引号的字符串中。

    • (b) 然后 - 这一步应该不是必需的 - 你需要 \-escape 嵌入 " 字符。您希望外部程序看到

      • 这是一个长期存在的令人讨厌的错误,至少存在 PowerShell 7.2可能在 7.3 中得到修复 - 请参阅 this answer .

    Re (a),您有以下选择:

    • '...'-quoting(单引号),其中您可以按原样使用"

      • '{ "spec": "none" }'
      • '...' 中的所有内容字面意思 - 不会发生扩展(插值)。
    • "..."-quoting(双引号),其中可以使用`"""嵌入"字符:

      • "{ `"spec`": `"none`" }" - ` 是 PowerShell 的通用转义字符。
      • "{ ""spec"": ""none"" }" - "-特定转义(加倍)
      • "..." 的内容受制于 扩展(插值),这意味着您可以在此类字符串中引用变量 ($var) 或子表达式 ($(1 + 2)),PowerShell 将其替换为它们的值 - 有关 PowerShell 的可扩展字符串的更多信息,请参阅this answer

    如果您将此类字符串传递给其他 PowerShell 命令(cmdlet、函数或脚本),无需进一步操作 ;例如:

    PS> Write-Output '3" of rain'
    3" of rain
    

    Re (b) - 即将此类字符串传递给外部程序 - 您另外需要\-escape嵌入的" 字符。

    • 应用手动转义到上面的例子:

      • '{ \"spec\": \"none\" }'
      • "{ \`"spec\`": \`"none\`" }"
      • "{ \""spec\"": \""none\"" }"
    • 转义以编程方式应用于预先存在的字符串:

      • 将逐字的" 替换为逐字的\",以及任何预先存在的、紧接在前面的 \\\

        • $str = '3" of rain'; $escapedStr = $str -replace '([\\]*)"', '$1$1\"'

        • 也就是说,要让外部程序最终逐字查看值 3" of rain,您必须从 PowerShell 传递文字值 3\" of rain\-escaping 是 PowerShell 作为 shell 应该在幕后自动执行的操作,但目前没有。

    • Windows PowerShell 中存在一个附加错误 - 已在 PowerShell Core 中修复 - 错误地处理带有 unbalanced 嵌入 " 字符。如果"第一个单词的一部分

      • 例如,上述技术不适用于 3" of rain 等文字值;也就是说,将其转义为 '3\" of rain' 确实 not 按预期工作 - 相反,您必须使用以下怪物:`"3\`" of rain`",这在技术上是一系列单独的、未引用的参数,这意味着 ( a) 不支持字符串单词之间的多个空格(它们被折叠成一个空格)和 (b) PowerShell 元字符,例如& < > $ & | @ {,必须单独使用`-转义。
      • 请注意,只有当" 是值中第一个单词的一部分,并且第一个单词前面没有空格时才会出现错误(尽管带有前导空格的参数很少有用);例如,'3 \" of rain' 将再次起作用,因为不平衡的 " 不是第一个单词的一部分。

    示例

    以下使用choice.exe 作为示例外部程序,因为它可以重新利用(通过选项/d Y /t 0)仅回显它给出的提示字符串,它显示了它如何接收从 PowerShell 传递的字符串:

    & {
      # Note: For preview versions of v7.2, deactivate the experimental
      #       feature that fixes the problem, so as to show the original problem.   
      $PSNativeCommandArgumentPassing = 'Legacy'
    
      # Use manual \-escaping to pass what should be received as
      # verbatim { "spec": "none" } to an external program.
      choice /m '{ \"spec\": \"none\" }' /d Y /t 0
    }
    

    以上输出{ "spec": "none" } [Y,N]?Y,表示手动转义的"字符。被逐字接收" 字符。由外部程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 2021-01-07
      相关资源
      最近更新 更多