【问题标题】:How do I replicate the Azure Resource Manager template uniquestring() function in Powershell?如何在 Powershell 中复制 Azure 资源管理器模板 uniquestring() 函数?
【发布时间】:2022-03-04 15:58:55
【问题描述】:

我有一个 Azure 托管的服务,它使用 ARM 模板自动部署(在我们的构建过程中),该服务的多个实例位于不同的资源组中。一些资源需要全局唯一名称,为了支持这一点,我使用uniquestring 函数(通常针对资源组 ID)来生成部分资源名称。名称遵循模板模式,例如实例名称 + 组件名称 + 唯一字符串 = "Example.WebAPI.abcd1234efgh5"

我的问题后来在使用 Powershell 脚本对这些资源执行维护时出现 - 我需要资源名称,这意味着使用相同的模板从实例、组件和资源组 ID 生成名称。但是,Powershell 中没有任何函数针对相同的输入返回与 ARM uniquestring 函数相同的值。

据我所知,uniquestring 只是生成输入字符串的哈希并将其作为 13 个字符的表示形式返回;有谁知道这个哈希过程的细节,所以它可以在 Powershell 中复制,或者是否已经完成?

我查看了Can I call ARM template functions outside the JSON deployment template? 的答案,但这需要在初始 ARM 模板中使用输出参数,并假定立即使用该值;而在我的用例中,我在初始部署几周或几个月后需要资源名称。

【问题讨论】:

    标签: powershell azure templates


    【解决方案1】:

    该函数在任何地方都没有记录,但它是确定性的,这意味着如果您提供相同的输入,您总是会得到相同的输出,因此无需担心。

    如果您之后需要识别资源,您可以想出一堆解决方法,您始终可以使用Get-AzureRmResourceGroupDeployment 获取部署的输出,或者您可以使用您可以动态推断的特定内容标记资源或您可以使用创建时间和其他间接因素等因素来过滤资源

    【讨论】:

    • 我知道uniquestring 在 ARM 模板中是确定性的,我的问题是它在 Powershell 脚本中不可用
    • 对此你无能为力,就像我说的,使用相同的输入,不应该太难
    • 对什么使用相同的输入?我没有从 Powershell 调用 ARM 模板,我使用的是不包含类似功能的 AzureRM 模块。我确实需要的资源名称是一个计算值,但该计算需要uniquestring 函数并且该函数在 ARM 模板之外不可用
    • 更新了答案,我以为你问的是相反的
    【解决方案2】:

    你可以看这里:https://docs.microsoft.com/en-us/archive/blogs/389thoughts/get-uniquestring-generate-unique-id-for-azure-deployments

    #!/usr/bin/env pwsh
    
    function Get-UniqueString ([string]$id, $length=13)
    {
        $hashArray = (new-object System.Security.Cryptography.SHA512Managed).ComputeHash($id.ToCharArray())
            -join ($hashArray[1..$length] | ForEach-Object { [char]($_ % 26 + [byte][char]'a') })
    }
    
    Get-UniqueString "foobar"
    

    【讨论】:

      【解决方案3】:

      我参加聚会有点晚了,但下面的 Powershell 脚本应该可以完成这项工作。

      这是从具有关键字“unchecked”的 C# 翻译而来,因此函数 uncheckedUInt32Multiply 和 uncheckedUInt32Addition 用于在将数字相乘时不会导致溢出。

      因为我刚刚从 C# 过渡到 Powershell,所以我不能对此表示赞赏。

      C#函数源码来自:https://www.nuget.org/packages/Azure.Deployments.Expression/

      用法:

      # Pass an ordinary string
      .\ArmUniqueStringGenerator.ps1 -InputStringValue "test example"
      
      # Get Resource group name and pass the id to unique string generator.
      (Get-AzResourceGroup -Name <Resource Group Name>).ResourceId | .\ArmUniqueStringGenerator.ps1
      
          param(
              [Parameter(
                  Mandatory=$true,
                  ValueFromPipeline=$true)]
              [string]$InputStringValue
          )
      
          #region Functions
          function GenerateUniqueString {
              param(
                  [Parameter(Mandatory=$true)]
                  [string]$InputString,
                  [uint]$seed = 0u
              )
      
              [uint[]] $dataArray = [System.Text.Encoding]::UTF8.GetBytes($InputString)
      
              [int] $num =  $dataArray.Length
              [uint] $num2 = $seed
              [uint] $num3 =  $seed
      
              $index = 0
      
              for ($index = 0; $index + 7 -lt $num; $index += 8) {
                  [uint] $num4 = [uint]($dataArray[$index] -bor ($dataArray[$index + 1] -shl 8) -bor ($dataArray[$index + 2] -shl 16) -bor ($dataArray[$index + 3] -shl 24))
                  [uint] $num5 = [uint] ($dataArray[$index + 4] -bor ($dataArray[$index + 5] -shl 8) -bor ($dataArray[$index + 6] -shl 16) -bor ($dataArray[$index + 7] -shl 24))
                  $num4 = uncheckedUInt32Multiply $num4 597399067
                  $num4 = scramble -value $num4 -count 15
                  $num4 = uncheckedUInt32Multiply $num4 2869860233u
                  $num2 = $num2 -bxor $num4
                  $num2 = scramble -value $num2 -count 19
                  $num2 = uncheckedUInt32Addition $num2 $num3
                  $num2 = uncheckedUInt32Addition (uncheckedUInt32Multiply $num2 5) 1444728091
                  $num5 = uncheckedUInt32Multiply $num5 2869860233u
                  $num5 = scramble -value $num5 -count 17
                  $num5 = uncheckedUInt32Multiply $num5 597399067
                  $num3 = $num3 -bxor $num5
                  $num3 = scramble -value $num3 -count 13
                  $num3 = uncheckedUInt32Addition $num3 $num2
                  $num3 = uncheckedUInt32Addition (uncheckedUInt32Multiply $num3 5) 197830471
      
              }
      
              $num6 = [int]($num - $index)
              if ($num6 -gt 0) {
      
                  $elseVal = switch($num6)
                  {
                      2 { 
                          [uint]($dataArray[$index] -bor ($dataArray[$index + 1] -shl 8)) 
                      } 
                      3 { 
                          [uint]($dataArray[$index] -bor ($dataArray[$index + 1] -shl 8) -bor ($dataArray[$index + 2] -shl 16)) 
                      }
                      default { 
                          $dataArray[$index] 
                      }
                  }
                  
                  $num7 = [uint](($num6 -ge 4) ? ([uint]($dataArray[$index] -bor ($dataArray[$index + 1] -shl 8) -bor ($dataArray[$index + 2] -shl 16) -bor ($dataArray[$index + 3] -shl 24))) : $elseVal)
                  $num7 = uncheckedUInt32Multiply $num7 597399067
                  $num7 = scramble -value $num7 -count 15
                  $num7 = uncheckedUInt32Multiply $num7 2869860233u
                  $num2 = $num2 -bxor $num7
                  if ($num6 -gt 4)
                  {
                      $value = switch($num6)
                      {
                          6 { 
                              uncheckedUInt32Multiply ($dataArray[$index + 4] -bor ($dataArray[$index + 5] -shl 8)) -1425107063
                          } 
                          7 { 
                              uncheckedUInt32Multiply ($dataArray[$index + 4] -bor ($dataArray[$index + 5] -shl 8) -bor ($dataArray[$index + 6] -shl 16)) -1425107063
                          } 
                          default { 
                              uncheckedUInt32Multiply ($dataArray[$index + 4]) -1425107063
                          } 
                      }
                      $value = scramble -value $value -count 17
                      $value = uncheckedUInt32Multiply $value 597399067
                      $num3  = $num3 -bxor $value
                  }
              }
      
      
              $num2 = $num2 -bxor [uint]$num
              $num3 = $num3 -bxor [uint]$num
              $num2 = uncheckedUInt32Addition $num2 $num3
              $num3 = uncheckedUInt32Addition $num3 $num2
              $num2 = $num2 -bxor $num2 -shr 16
              $num2 = uncheckedUInt32Multiply $num2 2246822507u
              $num2 = $num2 -bxor $num2 -shr 13
              $num2 = uncheckedUInt32Multiply $num2 3266489909u
              $num2 = $num2 -bxor $num2 -shr 16
              $num3 = $num3 -bxor $num3 -shr 16
              $num3 = uncheckedUInt32Multiply $num3 2246822507u
              $num3 = $num3 -bxor $num3 -shr 13
              $num3 = uncheckedUInt32Multiply $num3 3266489909u
              $num3 = $num3 -bxor $num3 -shr 16
              $num2 = uncheckedUInt32Addition $num2 $num3
              $num3 = uncheckedUInt32Addition $num3 $num2
      
              $final = ([ulong]$num3 -shl 32) -bor $num2
              $uniqueString = Base32Encode $final
              return $uniqueString
          }
      
      
          $encodeLetters = "abcdefghijklmnopqrstuvwxyz234567"
      
          function scramble {
              param (
                  [uint] $value,
                  [int] $count
              )
              return ($value -shl $count) -bor ($value -shr 32 - $count)
          }
      
      
          function Base32Encode {
              param (
                  [ulong] $longVal
              )
              $strOutput = ""
              for ($i = 0; $i -lt 13; $i++) {
                  $charIdx = [int]($longVal -shr 59)
                  $charAddition = $encodeLetters[$charIdx]
                  $strOutput = $strOutput + $charAddition
                  $longVal = $longVal -shl 5;
      
              }
              return $strOutput
          }
      
          function Base32Decode {
              param (
                  [string] $encodedString
              )
              $bigInteger = [Numerics.BigInteger]::Zero
              for ($i = 0; $i -lt $encodedString.Length; $i++) {
                  $char = $encodedString[$i]
                  $ltrIdx = $encodeLetters.IndexOf($char)
                  $bigInteger = ($bigInteger -shl 5) -bor $ltrIdx
              }
      
              return $bigInteger / 2
          }
      
          function uncheckedUInt32Multiply {
              param (
                  [long] $nbrOne,
                  [long] $nbrTwo
              )
      
              $nbrOnePos = $nbrOne -lt 0 ? [uint]::MaxValue - (-$nbrOne) + 1 : $nbrOne
              $nbrTwoPos = $nbrTwo -lt 0 ? [uint]::MaxValue - (-$nbrTwo) + 1 : $nbrTwo
      
              $uintMaxVal = [uint]::MaxValue
      
              $longMultiplyResult = ([ulong]$nbrOnePos * [ulong]$nbrTwoPos)
      
              $remainder = $longMultiplyResult % $uintMaxVal
              $totalDevisions = ($longMultiplyResult - $remainder) / $uintMaxVal
      
              $result = $remainder - $totalDevisions
              
              if ($result -lt 0) {
                  return ($uintMaxVal - (-$result)) + 1
              }
              return $result
          }
      
          function uncheckedUInt32Addition {
              param (
                  [uint] $nbrOne,
                  [uint] $nbrTwo
              )
      
              $nbrOnePos = $nbrOne -lt 0 ? [uint]::MaxValue - (-$nbrOne) + 1 : $nbrOne
              $nbrTwoPos = $nbrTwo -lt 0 ? [uint]::MaxValue - (-$nbrTwo) + 1 : $nbrTwo
      
              $uintMaxVal = [uint]::MaxValue
      
              $longAdditionResult = ($nbrOnePos + $nbrTwoPos)
              $remainder = $longAdditionResult % $uintMaxVal
              $totalLoops = ($longAdditionResult - $remainder) / $uintMaxVal
              $result = [System.Math]::Abs($remainder - $totalLoops)
      
              return $result
          }
          #endregion
      
          $uniquestring = GenerateUniqueString -InputString $InputStringValue
          return $uniqueString
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-08
        • 2016-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多