【问题标题】:Terraform azurerm_virtual_machine_extension, run local PowerShell Script using CustomScriptExtensionTerraform azurerm_virtual_machine_extension,使用 CustomScriptExtension 运行本地 PowerShell 脚本
【发布时间】:2020-06-01 14:08:28
【问题描述】:

如何在 terraform azurerm_virtual_machine_extension 中运行本地(不存储到 blob 存储帐户)PowerShell 脚本

文件夹有

  1. main.tf
  2. 安装.ps1

    资源“azurerm_virtual_machine_extension”“软件”{ 名称=“安装软件” resource_group_name = azurerm_resource_group.azrg.name virtual_machine_id = azurerm_virtual_machine.vm.id 发布者 = "Microsoft.Compute" type = "自定义脚本扩展" type_handler_version = "1.9"

      settings = <<SETTINGS
        { 
          "commandToExecute": "powershell -ExecutionPolicy Unrestricted -File \"install.ps1\""
        } 
        SETTINGS
    } 
    

    但失败了

    [
            {
                "code": "ComponentStatus/StdOut/succeeded",
                "level": "Info",
                "displayStatus": "Provisioning succeeded",
                "message": "Windows PowerShell \r\nCopyright (C) Microsoft Corporation. All rights reserved.\r\n\r\n"
            },
            {
                "code": "ComponentStatus/StdErr/succeeded",
                "level": "Info",
                "displayStatus": "Provisioning succeeded",
                "message": "The argument 'install.ps1' to the -File parameter does not exist. Provide the path to an existing '.ps1' file as an argument to the -File parameter.\r\n"
            }
        ]
    

任何线索。

谢谢

【问题讨论】:

    标签: powershell terraform


    【解决方案1】:

    这对我有用。

    resource "azurerm_virtual_machine_extension" "software" {
      name                 = "install-software"
      resource_group_name  = azurerm_resource_group.azrg.name
      virtual_machine_id   = azurerm_virtual_machine.vm.id
      publisher            = "Microsoft.Compute"
      type                 = "CustomScriptExtension"
      type_handler_version = "1.9"
    
      protected_settings = <<SETTINGS
      {
        "commandToExecute": "powershell -command \"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(data.template_file.tf.rendered)}')) | Out-File -filepath install.ps1\" && powershell -ExecutionPolicy Unrestricted -File install.ps1"
      }
      SETTINGS
    }
    
    data "template_file" "tf" {
        template = "${file("install.ps1")}"
    } 
    

    【讨论】:

      【解决方案2】:

      这里有一个更漂亮的解决方案,基于gsgill76's answer。 请注意,我们应该使用textencodebase64 (Terraform >= v0.14),因为它允许指定 Unicode 编码,这是
      powershell -encodedCommand 所期望的。

      resource "azurerm_virtual_machine_extension" "software" {
        name                 = "install-software"
        resource_group_name  = azurerm_resource_group.azrg.name
        virtual_machine_id   = azurerm_virtual_machine.vm.id
        publisher            = "Microsoft.Compute"
        type                 = "CustomScriptExtension"
        type_handler_version = "1.9"
      
        protected_settings = <<SETTINGS
        {
           "commandToExecute": "powershell -encodedCommand ${textencodebase64(file("install.ps1"), "UTF-16LE")}"
        }
        SETTINGS
      }
      

      【讨论】:

        【解决方案3】:

        如果这对任何人有帮助,我设法将参数从数据“template_file”传递到 PowerShell 命令行以在服务器上执行。

        在我的情况下实际上不需要凭据,但我还是想通过它们。就我而言,这些凭据是从 Azure 中的 VM 设置中获取的。

        resource "azurerm_virtual_machine_extension" "software" {
          name                 = "install-software"
        #  resource_group_name  = azurerm_resource_group.main.name
          virtual_machine_id   = azurerm_windows_virtual_machine.ADVM1.id
          publisher            = "Microsoft.Compute"
          type                 = "CustomScriptExtension"
          type_handler_version = "1.9"
        
          protected_settings = <<SETTINGS
          {    
            "commandToExecute": "powershell -command \"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(data.template_file.DomainControllerSetup.rendered)}')) | Out-File -filepath DomainControllerSetup.ps1\" && powershell -ExecutionPolicy Unrestricted -File DomainControllerSetup.ps1 -DomainName ${data.template_file.DomainControllerSetup.vars.DomainName} -AdmincredsUserName ${data.template_file.DomainControllerSetup.vars.AdmincredsUserName} -AdmincredsPassword ${data.template_file.DomainControllerSetup.vars.AdmincredsPassword}" 
          }
          
          SETTINGS
        }
        
        data "template_file" "DomainControllerSetup" {
            template = "${file("DomainControllerSetup.ps1")}"
            vars = {
                DomainName              = "azlab.local"
                AdmincredsUserName      = "${azurerm_windows_virtual_machine.ADVM1.admin_username}"
                AdmincredsPassword      = "${azurerm_windows_virtual_machine.ADVM1.admin_password}"
          }
        } 
        

        这是我的“创建新森林”脚本——如果有帮助的话。此示例中未使用凭据,仅使用了域名。但是我想保留它,以防我想将成员服务器提升到现有域中。

        
        [CmdletBinding()]
        
        param 
        ( 
            [Parameter(ValuefromPipeline=$true,Mandatory=$true)] [string]$DomainName,
            [Parameter(ValuefromPipeline=$true,Mandatory=$true)] [string]$AdmincredsUserName,
            [Parameter(ValuefromPipeline=$true,Mandatory=$true)] [string]$AdmincredsPassword
        )
        
        $username = $AdmincredsUserName
        $password = ConvertTo-SecureString -AsPlainText $AdmincredsPassword -Force
        $Cred = New-Object System.Management.Automation.PSCredential ($username, $password)
        
        install-windowsfeature AD-Domain-Services -IncludeManagementTools
        
        Install-ADDSForest `
        -DomainName $DomainName `
        -SafeModeAdministratorPassword $password `
        -CreateDnsDelegation:$false `
        -DatabasePath "C:\Windows\NTDS" `
        -InstallDns:$true `
        -LogPath "C:\Windows\NTDS" `
        -NoRebootOnCompletion:$false `
        -SysvolPath "C:\Windows\SYSVOL" `
        -Force:$true
        
        

        【讨论】:

          【解决方案4】:

          感谢gsgill76 的工作命令!

          这里是如何使用有利于数据源的函数

          locals {
            scriptName     = "install.ps1"
            scriptRendered = filebase64("${path.module}/${local.scriptName}")
            # use templatefile() to parse script parameters
            ifTemplateFile = base64encode(templatefile("${path.module}/${local.scriptName}", {}))
            commandToExecute = jsonencode({
              commandToExecute = "powershell -command \"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${local.scriptRendered}')) | Out-File -filepath ${local.scriptName}\" && powershell -ExecutionPolicy Unrestricted -File ${local.scriptName}"
            })
          }
          
            # settings block will look like
            protected_settings = local.commandToExecute
          

          path.module 假设脚本与您的 terraform 代码位于同一目录中

          filebase64

          templatefile

          jsonencode

          【讨论】:

            猜你喜欢
            • 2018-08-14
            • 2020-11-06
            • 1970-01-01
            • 2019-06-02
            • 1970-01-01
            • 2018-06-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多