powershell - 如何在 Powershell 中复制 Azure 资源管理器模板 uniquestring() 函数?

标签 powershell azure templates

我有一个 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 脚本应该可以完成这项工作。

这是从具有关键字“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

关于powershell - 如何在 Powershell 中复制 Azure 资源管理器模板 uniquestring() 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48190183/

相关文章:

arrays - 如何对数组中的元素之间没有空格的字符串进行字符串化处理?

xml - 使用 PowerShell 加载 XML 字符串

python - 获取 Azure 中连接到不同订阅中的工作区的虚拟机的日志分析工作区 ID

asp.net - 使用 ASP.NET Core 和 EntityFramework 7 通过 Azure 中的迁移更改来更新生产数据库

powershell - 错误处理 - PowerShell 脚本

arrays - 如何从 json 文件中删除空对象

azure - 需要仅为 VM 的标签部署 Azure 策略

c++ - 如何默认构造迭代器的value_type作为函数中的默认参数?

c++ - 使用两个数组创建 map

c++ - 调用参数多于参数的函数/仿函数