Azure DevOps流水线中的变量组YAML变量表达式

4
我在使用 AzureKeyVault 任务的变量表达式时遇到了困难。azureSubscription 和 KeyVaultName 值表达式都不能被解析为变量组中的变量。如果我在 yaml 文件中手动定义这些变量,无论是在 azure-pipelines.yml 中还是在我在阶段开头导入的模板 variables_test.yml 中,它都可以工作。
我在文档中读到,应该像这样使用变量组中的变量 $(var),但然后它会抛出一个错误,说订阅 '$(var)' 不存在。

Template: azure-pipelines.yml:

- stage: Test

  variables:
  - template: variables_Test.yml  # Template reference
  - group: testVariableGroup

  dependsOn: []

  jobs:

  - job: Test
    
    steps:

    - task: AzureKeyVault@1
      inputs:
        azureSubscription: ${{ variables.spn_kv_app }}
        KeyVaultName: ${{ variables.keyVaultName }}
        SecretsFilter: '*'

从暂存区的日志中,我可以看到变量组中设置的变量:

Job preparation parameters
Variables:
  keyVaultName: $[ variablegroups.testVariableGroup.keyVaultName ]
  resourceGroupName: $[ variablegroups.testVariableGroup.resourceGroupName ]
  spn_cd_app: $[ variablegroups.testVariableGroup.spn_cd_app ]
  spn_kv_app: $[ variablegroups.testVariableGroup.spn_kv_app ]
  storageAccountName: $[ variablegroups.testVariableGroup.storageAccountName ]

重要的是需要注意,这些变量在变量组中没有设置为机密变量。

顺便说一句,对于任何感兴趣的人,我创建了工单:

https://github.com/MicrosoftDocs/vsts-docs/issues/7586

https://developercommunity.visualstudio.com/content/problem/949342/azuresubscription-serviceconnection.html

如果有任何问题得到解决,我会发布答案。

有没有通过开发者社区解决这个问题的机会?链接已经失效了。:/ 我在除了密钥保管库之外的任务中遇到了与azureSubscription和其他几个值相同的问题。 - Gregg L
@GreggL 老实说,我忘了这件事,因为我们通过在 YAML 中硬编码名称来解决了它。目前对我们来说这很有效,但是当我们需要覆盖更多的 azureSubscriptions 时,我可以看到这可能会成为一个问题。 - Repcak
没关系,我仍然感谢您的回复!顺便说一下,我通过创建“仅变量”模板文件来解决了这个问题。我们部署到的每个环境都有一个相应的“[env_name]-variables.yml”文件,其中包含该环境的值,并将其检入源代码控制。适当的作业加载相应的模板(文件)(作为变量),现在可以获取任务所需的“环境”值。有点笨拙,但现在还是可以管理的。 - Gregg L
这个示例中的方法对于像 Azure Powershell 中的 AzureSubscription 字段这样的任务也适用吗?因为我们还使用基于变量的模板来控制版本。 - Repcak
它适用于Azure CLI任务中的azureSubscription字段,但我还没有尝试过Azure Powershell. - Gregg L
2个回答

2
我认为这不是一个bug,而是一个产品限制。有两种类型的字段不能分配“外部”(即来自变量组)变量:
  • 指向服务连接的字段,在许多不同类型的任务中使用,例如ARM模板部署。(根据任务的不同可能有很多不同的名称,例如“azureSubscription”,“serviceConnection”等)
  • 环境名称,在部署作业中是强制性的。
实际上,这已经有文档说明了,但在一个非常隐蔽的地方(应该在主变量页面上!)。请参见这里的最后一段。
你可能会说:“但我在XYZ情况下使用过它,并且它有效!”我会同意你的看法,但那是非常不可预测的,取决于任务的类型。作为一个经验法则,我从不在变量组中使用服务连接和环境。 但是有一个解决方法!不要使用变量组,而是在主管道中使用具有静态值的变量(稍后可以调用任意数量的模板),甚至可以使用“变量文件”,它将像变量组一样工作,一个包含这些变量及其值的外部yaml模板。因此,通过这样做,您可以将这些参数保存在一个地方,而不必在解决方案中的每个管道和模板中查找它们。
以下是最基本的示例: main_pipeline.yml:
variables:
  - service_connection: my-service-connection-name
  - environment: Production

jobs:
  - deployment: JOB_DEPLOY
    environment: ${{ variables.environment }}
    strategy:
      runOnce:
        deploy:
          steps:
            - task: AzurePowerShell@5
              inputs:
                azureSubscription: '${{ variables.service_connection }}'
                ScriptType: 'FilePath'
                ScriptPath: '$(Build.Repository.LocalPath)/my_script.ps1'

你可以指向外部变量模板: main_pipeline.yml:
variables:
  - template: project-settings.yml@self

jobs:
  - deployment: JOB_DEPLOY
    environment: ${{ variables.environment }}
    strategy:
      runOnce:
        deploy:
          steps:
            - task: AzurePowerShell@5
              inputs:
                azureSubscription: '${{ variables.service_connection }}'
                ScriptType: 'FilePath'
                ScriptPath: '$(Build.Repository.LocalPath)/my_script.ps1'

project-settings.yml:

variables:
  - name: service_connection
    value: my-service-connection-name
  - name: environment
    value: Production

这两个示例的工作方式相同。 重要的是将静态值放入文件中,并使用所谓的“模板表达式”语法(${{ }})。 原因是模板表达式在运行管道之前被处理,此时系统只能使用静态值。这使得服务连接和环境能够在需要时获取变量的值。


1

Azure Devops Pipeline中的变量组yaml变量表达式

应该使用$(var)进行工作。请尝试检查以下测试yaml文件:

主要Yaml:

trigger:
- master

variables:
- group: Test2

pool:
  vmImage: 'windows-latest'

stages:

- template: azure-pipelines.yml

模板azure-pipelines.yml

stages:
- stage: Test

  dependsOn: []

  jobs:

  - job: Test

    steps:

    - task: AzureKeyVault@1
      inputs:
        azureSubscription: $(spn_kv_app)
        KeyVaultName: $(keyVaultName)
        SecretsFilter: '*'

以及我的变量组:

enter image description here

根据测试结果:

enter image description here

所以,在我的端上它运行良好。请检查您的变量组名称和变量的名称。

希望这可以帮助您。


谢谢回复。我会在周末检查并回复! - Repcak
3
我测试了你的解决方案,确实有效。但是,在主上下文中的主yaml文件中导入了变量组(variable group)。我有多个环境(15个),这意味着有相同数量的阶段(15个)和变量组(15个)。而且所有变量组中都有相同的变量名称。我需要在阶段级别导入变量组。由于某种原因,从variables_Test.yml中导入的变量可以使用,但变量组却不能工作。 - Repcak
1
@Repcak,抱歉由于周末回复延迟。我认为这是由于Azure DevOps的初始化引起的。对于模板Azure DevOps,它只会进行一些简单的验证,不会解析yml文件。这就是为什么您可以从variables_Test.yml获取变量,而不能从变量组变量获取的原因。 - Leo Liu
1
这是一个问题。我认为我们应该能够在阶段级别引用变量组并期望相同的行为。 - Eric Hansen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接