我正在尝试创建一个 Azure DEvOps 管道,使用 terraform 部署虚拟机,然后使用 WinRm 连接到该虚拟机以执行脚本,但我找不到将从 output.tf 捕获的公共 IP 传递到要在连接上使用的管道的方法。希望有人能给出一些建议来解决这个问题。

请参阅我的 .yml 文件

    trigger:
  none

pool:
  vmImage: 'windows-latest'

variables:
  bkrg: 'CloudOPs_OPS_RG'
  bkstorage: 'xxxxxxxxxx'
  bkcontainer: 'terraformmtp'
  bkkey: 'terraform.tfstate'
  adminUsername: 'xxxxxxxxxxxx'
  adminPassword: 'xxxxxxxxxxxxx' 

parameters:
  - name: bacpacSasToken
    displayName: 'Bacpac SAS Token'
    type: string

stages:
- stage: 'tfvalidate'
  jobs:
    - job: 'validate'
      continueOnError: false
      steps:
        - task: TerraformInstaller@0
          displayName: 'Install Terraform'
          inputs:
            terraformVersion: 'latest'

        - task: TerraformTaskV3@3
          displayName: 'Terraform init'
          inputs:
            provider: 'azurerm'
            command: 'init'
            backendServiceArm: 'xxxxxxxxxxxxxxxx'
            backendAzureRmResourceGroupName: '$(bkrg)'
            backendAzureRmStorageAccountName: '$(bkstorage)'
            backendAzureRmContainerName: '$(bkcontainer)'
            backendAzureRmKey: '$(bkkey)'

        - task: TerraformTaskV3@3
          displayName: 'Terraform validate'
          inputs:
            provider: 'azurerm'
            command: 'validate'

- stage: 'tfdeploy'
  condition: succeeded('tfvalidate')
  dependsOn: 'tfvalidate'
  jobs:
    - job: 'apply'
      steps:
        - task: TerraformInstaller@0
          displayName: 'Install Terraform'
          inputs:
            terraformVersion: 'latest'

        - task: TerraformTaskV3@3
          displayName: 'Terraform init'
          inputs:
            provider: 'azurerm'
            command: 'init'
            backendServiceArm: 'xxxxxxxxxxxxxxxx'
            backendAzureRmResourceGroupName: '$(bkrg)'
            backendAzureRmStorageAccountName: '$(bkstorage)'
            backendAzureRmContainerName: '$(bkcontainer)'
            backendAzureRmKey: '$(bkkey)'

        - task: TerraformTaskV3@3
          displayName: 'Terraform plan'
          inputs:
            provider: 'azurerm'
            command: 'plan'
            environmentServiceNameAzureRM: 'xxxxxxxxxxxxxxxx'

        - task: TerraformTaskV3@3
          displayName: 'Terraform apply'
          inputs:
            provider: 'azurerm'
            command: 'apply'
            environmentServiceNameAzureRM: 'xxxxxxxxxxxxxxxx'

        - task: PowerShell@2
          displayName: 'Capture public IP and push to pipeline variable'
          inputs:
            targetType: 'inline'
            script: |
              $tfOutput = terraform output -json | ConvertFrom-Json
              $publicIp = $tfOutput.public_ip.value
              Write-Host "##vso[task.setvariable variable=publicIp;isOutput=true]$publicIp"
              Write-Host "Captured Public IP: $publicIp"

- stage: 'bacpacoperations'
  condition: succeeded('tfdeploy')
  dependsOn: 'tfdeploy'
  jobs:
    - job: 'downloadbacpac'
      variables:
        public_ip: $[ stageDependencies.tfdeploy.apply.outputs['publicIp'] ]
      steps:
        - task: AzureCLI@2
          displayName: 'Azure CLI'
          inputs:
            azureSubscription: 'xxxxxxxxxxxxxxxx'
            scriptType: 'ps' 
            scriptLocation: 'inlineScript'
            inlineScript: |
              $publicip = "$(public_ip)"
              $username = "$(adminUsername)"
              $password = "$(adminPassword)"
              $securePassword = ConvertTo-SecureString $password -AsPlainText -Force
              $credential = New-Object System.Management.Automation.PSCredential ($username, $securePassword)
              $session = New-PSSession -ComputerName $publicip -Credential $credential -UseSSL -Port 5986
              Invoke-Command -Session $session -ScriptBlock { 
                cd $(System.DefaultWorkingDirectory)
                ./downloadbacpac.ps1 -bacpacSasToken "$(bacpacSasToken)" -localPath "f:\\"
              }
              Remove-PSSession -Session $session

这是我得到的错误

New-PSSession : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Provide an 
argument that is not null or empty, and then try the command again.
At D:\a\_temp\azureclitaskscript1726051757039_inlinescript.ps1:6 char:40
+ $session = New-PSSession -ComputerName $publicip -Credential $credent ...
+                                        ~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [New-PSSession], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewPSSessionCommand
 

##[error]Script failed with exit code: 1


最佳答案
1

要在中使用变量next stage,请在阶段中添加task namepowershell 任务。tfdeploy

        - task: PowerShell@2
          displayName: 'Capture public IP and push to pipeline variable'
          name: getip             # <-- add task name
          inputs:
            targetType: 'inline'
            script: |
              $tfOutput = terraform output -json | ConvertFrom-Json
              $publicIp = $tfOutput.public_ip.value
              Write-Host "##vso[task.setvariable variable=publicIp;isOutput=true]$publicIp"
              Write-Host "Captured Public IP: $publicIp"   # < -- make sure ip value output is correct

在下一阶段,将任务名称包含在变量表达式中:

      variables:
        public_ip: $[ stageDependencies.tfdeploy.apply.outputs['getip.publicIp'] ]

有关详细信息,请参阅文档

在 powershell 任务中,请确保代理 ip$publicIp正确输出,因为该值将被设置为下一阶段的输出变量值。