在使用 DevOps 触发基于 Bicep 的部署时缺少变量。

huangapple go评论72阅读模式
英文:

Missing variable when triggering bicep based deployment with devops

问题

我正在尝试使用Azure DevOps管道来部署Azure资源,使用一个Bicep文件。这个过程如果我使用PowerShell来部署是有效的,但是我在DevOps中遇到了一个问题。

在Bicep文件中,我有以下内容:

param environmentType string
var stgSubID = 'xxxx'
var prodSubID = 'xxxx'

var subscriptionID = (environmentType == 'prod') ? prodSubID : stgSubID

通过在部署时输入prodstg,我可以设置文件后面的某些其他值。

在DevOps中,我创建了以下管道,但它失败了,因为subscriptionID不存在。我想保留条件变量,而不是创建重复的管道,因为这只会使在此之后运行的管道变得更加复杂。

在一些搜索后,我找到了以下方法,但它也失败了。

trigger: none

pool:
  vmImage: ubuntu-latest

variables:
  - name: environment
    value: $(environment)
  - name: environmentType
    ${{ if eq( variables['environment'], 'stg') }}:
      value: $(stgSubID)
    ${{ if eq( variables['environment'], 'prod' ) }}:
      value: $(prodSubID)

jobs:
- job:
  steps:

  - task: AzureResourceManagerTemplateDeployment@3
    inputs:
      connectedServiceName: $(ServiceConnectionName)
      location: $(location)
      deploymentName: $(deploymentName)
      resourceGroupName: $(ResourceGroupName)
      csmFile: templates/newRegion.bicep
      csmParametersFile: deployments/newRegion/$(shortlocation)-$(environmentType).parameters.json
      overrideParameters: >
        -connectivitySubID $(connectivitySubID)
        -stgSubID $(stgSubID)
        -prodSubID $(prodSubID)
        -managementSubID $(managementSubID)
        -subscriptionID ${{variables.environmentType}}        

TL;DR 如何在Azure DevOps中根据运行时提供的输入将变量X设置为另一个变量的值,并将其传递给用于部署的Bicep文件。

英文:

I'm trying to use Azure devops pipelines to deploy azure resources using a bicep file.
This process works if I use powershell to deploy but I'm hitting a problem with devops.

In the bicep file I have the following

param environmentType string
var stgSubID = 'xxxx'
var prodSubID = 'xxxx'


var subscriptionID = (environmentType == 'prod') ? prodSubID : stgSubID

By entering prod or stg at deployment time I can set certain other values further down the file.

In devops I created the following pipeline but it failed because the subscriptionID wasn't present. I'd like to keep the conditional variable rather than creating duplicate pipelines as this will only complicate pipelines that run after this..

After some searching I came across this approach but it also fails.

trigger: none

pool:
  vmImage: ubuntu-latest

variables:
  - name: environment
    value: $(environment)
  - name: environmentType
    ${{ if eq( variables['environment'], 'stg') }}:
      value: $(stgSubID)
    ${{ if eq( variables['environment'], 'prod' ) }}:
      value: $(prodSubID)


jobs:
- job:
  steps:

  - task: AzureResourceManagerTemplateDeployment@3
    inputs:
      connectedServiceName: $(ServiceConnectionName)
      location: $(location)
      deploymentName: $(deploymentName)
      resourceGroupName: $(ResourceGroupName)
      csmFile: templates/newRegion.bicep
      csmParametersFile: deployments/newRegion/$(shortlocation)-$(environmentType).parameters.json
      overrideParameters: >
        -connectivitySubID $(connectivitySubID)
        -stgSubID $(stgSubID)
        -prodSubID $(prodSubID)
        -managementSubID $(managementSubID)
        -subscriptionID ${{variables.environmentType}}

TL:DR How do a set variable X to the value of another variable in Azure devops based on the input provided at run time and pass that to a bicep file for deployment.

答案1

得分: 1

你的YAML文件中似乎存在一个拼写错误。你将environment设定为等于environment的值,这将导致它解析为空。如果这是在部署时输入的变量,请参考关于变量和编译时表达式(${{}})的文档。运行时变量存在于编译时之后,因此你的变量无法解析;你不能在编译时表达式中使用运行时变量的值。

解决此问题的正确方法是使用多个阶段。为STG(测试环境)和PROD(生产环境)各创建一个阶段。然后你可以在部署时通过内置的阶段选择界面选择要部署的阶段。你可以将作业提取到一个模板中,并在适当的地方公开参数。

英文:

You have what appears to be a typo in your YAML. You set environment to be equal to the value of environment, which is going to resolve to empty. If it's a variable that's being entered at deployment time, please refer to the documentation on variables and compilation-time expressions (${{}}). Runtime variables exist after compilation time, so your variable cannot resolve; you cannot use runtime variable values in compilation-time expressions.

The correct way to address this is to use multiple stages. Have a stage for STG and a stage for PROD. Then you can choose the stage to deploy at deployment time via the built-in stage selection UI. You can extract the job to a template and expose parameters where appropriate.

答案2

得分: 1

尽管我认为你需要根据其他人的建议重新优化你的方法,但我会回答你的问题:TL:DR 如何根据运行时提供的输入设置变量 X 的值,并将其传递给用于部署的 bicep 文件,Azure DevOps 中如何实现。

根据你的示例,你有3个流水线变量:

  • $(environment)
  • $(stgSubID)
  • $(prodSubID)

当你在流水线执行期间设置 environment = stg 时,你将传递给 deployTask 的 environmentType 变量应该设置为 $(stgSubID),否则为 $(prodSubID)。

你可以通过引入一个额外的作业来解决这个问题,该作业将确定变量并将其输出到另一个作业中,使用 output variables

jobs:
- job: DetermineEnvironmentTypeJob
  steps:
    - pwsh: |
        $environmentType = "$(prodSubID)"
        if ("$(environment)" -eq "stg") {
          $environmentType = "$(stgSubID)"
        }
        Write-Host "##vso[task.setvariable variable=environmentTypeOutput;isoutput=true]$environmentType"        
      name: SetEnvironmentType

- job: TemplateDeploymentJob
  dependsOn: DetermineEnvironmentTypeJob
  variables:
    environmentType: $[ dependencies.DetermineEnvironmentTypeJob.outputs['SetEnvironmentType.environmentTypeOutput'] ]  
  steps:
    - pwsh: |
                Write-Host "Environment type $(environmentType)"
      displayName: DeployStep

验证:
流水线变量值:
$(stgSubID) = 1
$(stgProdID) = 2

测试 1:
将环境设置为 'stg' 执行流水线。
结果:environmentType = 1

测试 2
将环境设置为 'prod' 执行流水线。
结果:environmentType = 2

如果你需要使用这种方法,我建议至少使用 parameter,其中包含一组受限的值,如 stg、prod,而不是环境变量。

英文:

Although I think you need to refactor your approach as other guys stated I will answer your question: TL:DR How do a set variable X to the value of another variable in Azure DevOps based on the input provided at run time and pass that to a bicep file for deployment.

According to your example, you have 3 pipeline variables:

  • $(environment)
  • $(stgSubID)
  • $(prodSubID)

When you set environment = stg during pipeline execution then environmentType variable which you will be passing to deployTask should be set to $(stgSubID) else $(prodSubID).

You can resolve this problem by introducing an additional job that will determine the variable and output it to another job using the output variables

jobs:
- job: DetermineEnvironmentTypeJob
  steps:
    - pwsh: |
        $environmentType = "$(prodSubID)"
        if("$(environment)" -eq "stg") {
          $environmentType = "$(stgSubID)"
        }
        Write-Host "##vso[task.setvariable variable=environmentTypeOutput;isoutput=true]$environmentType"
      name: SetEnvironmentType

- job: TemplateDeploymentJob
  dependsOn: DetermineEnvironmentTypeJob
  variables:
    environmentType: $[ dependencies.DetermineEnvironmentTypeJob.outputs['SetEnvironmentType.environmentTypeOutput'] ]  
  steps:
    - pwsh: |
        Write-Host "Environment type $(environmentType)"
      displayName: DeployStep

Verification:
Pipeline variables value:
$(stgSubID) = 1
$(stgProdID) = 2

Test 1:
Execute pipeline with environment set to 'stg'.
Result: environmentType = 1

Test 2
Execute pipeline with environment set to 'prod'.
Result: environmentType = 2

If you need to use this approach I should at least recommend using the parameter with a restricted list of values stg, prod instead of environment variable.

huangapple
  • 本文由 发表于 2023年7月3日 17:58:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76603681.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定