在 ARM 部署脚本中使用 PowerShell 模块

Use PowerShell module in ARM deployment script

我有一个 ARM 模板,我希望在其中执行 powershell 脚本。在 中暗示应该可以在脚本中安装 powershell 模块。

我无法导入我想使用的模块。

这是ARM模板部署脚本:

        {
        "type": "Microsoft.Resources/deploymentScripts",
        "apiVersion": "2020-10-01",
        "name": "[concat('createServicePrincipalLogin-', parameters('databaseSettings').databases[copyIndex()].name)]",
        "location": "[resourceGroup().location]",
        "dependsOn": [
            "[resourceId('Microsoft.Sql/servers/databases', parameters('serverName'), parameters('databaseSettings').databases[copyIndex()].name)]",
            "[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
        ],
        "kind": "AzurePowerShell",
        "properties": {
          "azPowerShellVersion": "7.4",
          "timeout": "PT30M",
          "arguments": "[format(' -serverName {0} -databaseName {1} -userName {2} -password {3}  -appId {4} ', parameters('serverName'), parameters('databaseSettings').databases[copyIndex()].name, parameters('adminUsername'), parameters('adminPassword'), parameters('databaseSettings').databases[copyIndex()].appId)]",
          "scriptContent": "
            param(
              [string] [Parameter(Mandatory=$true)] $serverName,  
              [string] [Parameter(Mandatory=$true)] $databaseName,
              [string] [Parameter(Mandatory=$true)] $userName,
              [string] [Parameter(Mandatory=$true)] $password,
              [string] [Parameter(Mandatory=$true)] $appId
            )

            $ErrorActionPreference = 'Stop'
            $DeploymentScriptOutputs = @{}
            
            Install-Module -Name SqlServer
            Import-Module -Name SqlServer

            Invoke-Sqlcmd -ServerInstance $serverName
                          -database $databaseName
                          -username $userName
                          -password $password
                          -query 'CREATE USER $appId FROM EXTERNAL PROVIDER'
          ",
          "cleanupPreference": "OnSuccess",
          "retentionInterval": "P1D"
        },
        "copy": {
            "name": "dbgeobackupcopy",
            "count": "[length(parameters('databaseSettings').databases)]"
        }
    }

这是错误:

{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"},{"code":"BadRequest","message":"{\r
  \"code\": \"40822\",\r
  \"message\": \"This feature is not available for the selected database's edition (Standard).\",\r
  \"target\": null,\r
  \"details\": [\r
    {\r
      \"code\": \"40822\",\r
      \"message\": \"This feature is not available for the selected database's edition (Standard).\",\r
      \"target\": null,\r
      \"severity\": \"16\"\r
    }\r
  ],\r
  \"innererror\": []\r
}"},{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.IO.FileNotFoundException: The specified module 'SqlServer' was not loaded because no valid module file was found in any module directory.\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 14\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"}]}}

如果我删除 import 语句并简单地使用安装,我会收到一条错误消息,指示无法识别该命令。

{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"Conflict","message":"{\r
  \"status\": \"failed\",\r
  \"error\": {\r
    \"code\": \"ResourceDeploymentFailure\",\r
    \"message\": \"The resource operation completed with terminal provisioning state 'failed'.\",\r
    \"details\": [\r
      {\r
        \"code\": \"DeploymentScriptError\",\r
        \"message\": \"The provided script failed with the following error:\r\
System.Management.Automation.CommandNotFoundException: The term 'Invoke-Sqlcmd' is not recognized as a name of a cmdlet, function, script file, or executable program.\
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.\
   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)\
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)\
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)\
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)\
   at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)\
   at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)\
   at System.Management.Automation.PSScriptCmdlet.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess)\
   at System.Management.Automation.PSScriptCmdlet.DoEndProcessing()\
   at System.Management.Automation.CommandProcessorBase.Complete()\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/userscript.ps1: line 15\r\
at <ScriptBlock>, <No file>: line 1\r\
at <ScriptBlock>, /mnt/azscripts/azscriptinput/DeploymentScript.ps1: line 239. Please refer to https://aka.ms/DeploymentScriptsTroubleshoot for more deployment script information.\"\r
      }\r
    ]\r
  }\r
}"}

如何在部署脚本中使用 sql 模块?

为您的脚本资源试试这个 - 请注意一些参数与您的原始参数不同(无复制循环)。内联 PS 脚本可能难以调试,尤其是带有引号、空格、美元符号的参数(在 pwsh 中)。

与您的显着差异:

  • serverName 需要完全限定
  • invoke-sqlcmd中的换行符需要有反引号(我相信)
  • 引用密码和查询字符串
  • 使用 env vars 而不是 args(以节省更多引用麻烦)
  • 使用 -Force 安装模块(除非画廊是可信的)

当然还要确保防火墙控制与 sql

的所有连接

此外,如果传递参数合理,在脚本内部循环会更快。

        {
            "type": "Microsoft.Resources/deploymentScripts",
            "apiVersion": "2020-10-01",
            "name": "[concat('createServicePrincipalLogin-', parameters('databaseName'))]",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Sql/servers/databases', parameters('serverName'), parameters('databaseName'))]",
                "[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
            ],
            "kind": "AzurePowerShell",
            "properties": {
                "azPowerShellVersion": "7.4",
                "forceUpdateTag": "[parameters('alwaysRun')]",
                "timeout": "PT30M",
                "environmentVariables": [
                    {
                        "name": "SERVER_NAME",
                        "value": "[reference(resourceId('Microsoft.Sql/servers', parameters('serverName')), '2014-04-01').fullyQualifiedDomainName]"
                    },
                    {
                        "name": "DATABASE_NAME",
                        "value": "[parameters('databaseName')]"
                    },
                    {
                        "name": "USER_NAME",
                        "value": "[parameters('adminUsername')]"
                    },
                    {
                        "name": "PASSWORD",
                        "secureValue": "[parameters('adminPassword')]"
                    },
                                        {
                        "name": "QUERY",
                        "value": "[format('CREATE USER \"{0}\" FROM EXTERNAL PROVIDER', guid(resourceGroup().id))]"
                    }
                ],
                "scriptContent": "

            $ErrorActionPreference = 'Stop'
            $DeploymentScriptOutputs = @{}
            
            Install-Module -Name SqlServer -Force
            Import-Module -Name SqlServer

            Invoke-Sqlcmd -ServerInstance $ENV:SERVER_NAME `
                          -database $ENV:DATABASE_NAME `
                          -username $ENV:USER_NAME `
                          -password \"$ENV:PASSWORD\" `
                          -query $ENV:QUERY
          ",
                "cleanupPreference": "OnSuccess",
                "retentionInterval": "P1D"
            }
        }
 

有帮助吗?