Azure DevOps YAML 管道从传递的变量中删除引号和双反斜杠

Posted

技术标签:

【中文标题】Azure DevOps YAML 管道从传递的变量中删除引号和双反斜杠【英文标题】:Azure DevOps YAML Pipeline remove Quotes and double Backslashes from passed Variables 【发布时间】:2021-06-08 00:51:37 【问题描述】:

我有一个管道,它期望 Ansible-Playbook 作为队列时间的传递变量 (string)。将我的经典管道转换为 YAML 后,我发现 Playbook-String 中的 Quotes 丢失了。

经典管道通过 Playbook (")

---
  - 
    hosts: "all"
    gather_facts: true
    vars: 
      SoftwareFolder: "ansibleshare"
      SoftwareSource: "/mnt/ SoftwareFolder "
      AnsibleRoot: "D:/Ansible"
      Proxy: "http://www-cache.de:3128"
    tasks: 
      - 
        name: "set windows proxy settings"
        win_inet_proxy: 
          auto_detect: false
          proxy: " Proxy "
...

YAML 管道通过 Playbook (")

---
  - 
    hosts: all
    gather_facts: true
    vars: 
      SoftwareFolder: ansibleshare
      SoftwareSource: /mnt/ SoftwareFolder 
      AnsibleRoot: D:/Ansible
      Proxy: http://www-cache.de:3128
    tasks: 
      - 
        name: set windows proxy settings
        win_inet_proxy: 
          auto_detect: false
          proxy:  Proxy 
...

我尝试在传递之前将 Playbook 用单引号括起来 ('$yaml'),但这无济于事。

报价是剧本的重要组成部分,我很确定有原因,为什么管道会这样。但是作为一个利益相关者,当一个变量被传递而改变时感觉很糟糕,而且在经典的管道中没有必要这样做。

我该如何解决?


元:

18.170.30525.1 (Azure DevOps Server 2020)
on prem
API: "azure-devops-node-api": "^10.2.1"

编辑 1

ansible-playbooks 上下文中的另一个问题是 YAML 管道也会误解双反斜杠 \\,这对于 playbooks 中的 windows 路径非常重要:

经典管道通过 Playbook (\\)

      - 
        name: "msi install 7z"
        win_package: 
          path: " AnsibleRoot \\ SoftwareFolder \\7z\\7z.msi"
          state: "present"
      - 
        name: "exe install git client"
        win_package: 
          path: " AnsibleRoot \\ SoftwareFolder \\git\\Git.exe"
          state: "present"
          product_id: "git"
          creates_path: "C:\\Program Files\\Git\\cmd\\git.exe"
          arguments: 
            - "/SILENT"

YAML 管道通过 Playbook (\\)

      - 
        name: msi install 7z
        win_package: 
          path:  AnsibleRoot \ SoftwareFolder \7z\7z.msi
          state: present

      - 
        name: exe install git client
        win_package: 
          path:  AnsibleRoot \ SoftwareFolder \git\Git.exe
          state: present
          product_id: git
          creates_path: C:\Program Files\Git\cmd\git.exe
          arguments: 
            - /SILENT

这使得 YAML-Pipelines 很难用于该用例。 :(


编辑 2

YAML 管道内容

# NAME
name: "$(Build.BuildId)-$(Build.SourceBranchName) ($(Build.RequestedFor))"

# TRIGGER
trigger: none

# VARIABLES
variables:
  - name: "PathPlaybook"
    value: "ansible-playbook.yml"
  - name: "PathInventory"
    value: "ansible-inventory.yml"

# STAGES
stages:
  # ----------------------------------------------------------- BUILD
  - stage: "Build"

    # POOL
    pool:
      name: "Ansible"
    
    # JOBS
    jobs:
      - job:
        displayName: "Agent job"

        # STEPS
        steps:

          # BASH SCRIPT TO CREATE FILE FROM PASSED PARAMETER TO TARGET MACHINE
          - task: Bash@3
            inputs:
              targetType: "inline"
              script: |
                echo '$(Inventory)' > $(PathInventory)
                echo '$(Playbook)' > $(PathPlaybook)
                
                echo Inventory:
                echo '$(Inventory)'
                
                echo Playbook:
                echo '$(Playbook)'
          
          # ANSIBLE
          - task: Ansible@0
            displayName: Ansible Agent'
            inputs:
              playbookPathOnAgentMachine: '$(PathPlaybook)'
              inventoriesAgentMachine: file
              inventoryFileOnAgentMachine: '$(PathInventory)'
              failOnStdErr: false

说明

管道接收InventoryPlaybook 作为string Bash 任务将string 写入文件并生成我在上面发布的输出(更多出于调试原因) Ansible 执行文件

请记住。经典中的相同管道运行良好:


编辑 3:queueBuild 函数的参数

我为queueBuild函数使用了3个参数

``buildOption = 见下文 项目名称 = MyProject 忽略警告 = true

buildOption 作为对象

definition:id: 23
parameters:'"Inventory":"---\n  all: \n    hosts: \n      PTC-BLD-ADA5: \n        ansible_user: \"PTC-SVC-ADS-AGT\"\n        ansible_password: \"AgentPW2019\"\n        ansible_port: 5986\n        ansible_connection: \"winrm\"\n        ansible_winrm_transport: \"ntlm\"\n        ansible_winrm_server_cert_validation: \"ignore\"\n","Playbook":"---\n  - \n    hosts: \"all\"\n    gather_facts: true\n    vars: \n      SoftwareFolder: \"ansibleshare\"\n      SoftwareSource: \"/mnt/ SoftwareFolder \"\n      AnsibleRoot: \"D:\\\\Ansible\"\n      Proxy: \"http://www-cache.psitrans.de:3128\"\n    tasks: \n      - \n        name: \"set windows proxy settings\"\n        win_inet_proxy: \n          auto_detect: false\n          proxy: \" Proxy \"\n      - \n        name: \"create directory ansible\"\n        win_file: \n          path: \" AnsibleRoot \"\n          state: \"directory\"\n      - \n        name: \"copy software to target machine\"\n        win_copy: \n          src: \" SoftwareSource \"\n          dest: \" AnsibleRoot \"\n      - \n        name: \"exe install git client\"\n        win_package: \n          path: \" AnsibleRoot \\\\ SoftwareFolder \\\\git\\\\Git.exe\"\n          state: \"present\"\n          product_id: \"git\"\n          creates_path: \"C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe\"\n          arguments: \n            - \"/SILENT\"\n      - \n        name: \"msi install 7z\"\n        win_package: \n          path: \" AnsibleRoot \\\\ SoftwareFolder \\\\7z\\\\7z.msi\"\n          state: \"present\"\n"'
sourceBranch:'refs/heads/master'

构建选项为 JSON


  "definition":  "id": 23 ,
  "id": 23,
  "parameters": "\"Inventory\":\"---\n  all: \n    hosts: \n      PTC-BLD-ADA5: \n        ansible_user: \"PTC-SVC-ADS-AGT\"\n        ansible_password: \"AgentPW2019\"\n        ansible_port: 5986\n        ansible_connection: \"winrm\"\n        ansible_winrm_transport: \"ntlm\"\n        ansible_winrm_server_cert_validation: \"ignore\"\n\",\"Playbook\":\"---\n  - \n    hosts: \"all\"\n    gather_facts: true\n    vars: \n      SoftwareFolder: \"ansibleshare\"\n      SoftwareSource: \"/mnt/ SoftwareFolder \"\n      AnsibleRoot: \"D:\\\\Ansible\"\n      Proxy: \"http://www-cache.psitrans.de:3128\"\n    tasks: \n      - \n        name: \"set windows proxy settings\"\n        win_inet_proxy: \n          auto_detect: false\n          proxy: \" Proxy \"\n      - \n        name: \"create directory ansible\"\n        win_file: \n          path: \" AnsibleRoot \"\n          state: \"directory\"\n      - \n        name: \"copy software to target machine\"\n        win_copy: \n          src: \" SoftwareSource \"\n          dest: \" AnsibleRoot \"\n      - \n        name: \"exe install git client\"\n        win_package: \n          path: \" AnsibleRoot \\\\ SoftwareFolder \\\\git\\\\Git.exe\"\n          state: \"present\"\n          product_id: \"git\"\n          creates_path: \"C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe\"\n          arguments: \n            - \"/SILENT\"\n      - \n        name: \"msi install 7z\"\n        win_package: \n          path: \" AnsibleRoot \\\\ SoftwareFolder \\\\7z\\\\7z.msi\"\n          state: \"present\"\n\"",
  "sourceBranch": "refs/heads/master"

我的应用程序调用 queueBuild 函数并将 buildOption 作为对象,正如预期的那样。

重要的是要知道这对于 classic Pipelines 完全有效,只有 YAML Pipelines 对传递的参数进行更改,如上所述。

【问题讨论】:

您能否展示您的 YAML 管道中遇到此问题的相关部分? 你是如何将剧本字符串作为变量传递的。您在管道中使用了哪些任务? 我用管道内容扩展了我的问题。管道使用azure-devops-node-api": "^10.2.1" api 排队。 InventoryPlaybook 通过 queueBuild 函数作为 BuildInterfaces.Build 传递。点击here了解更多信息。 你能分享你在BuildInterfaces.Build中传递的参数字符串吗?我可以成功地将字符串传递给 yaml 管道,并保留" 和“\\”。 " 和 "\\ " 必须像这样 path: \\" AnsibleRoot \\\\\\\\ SoftwareFolder \\\\\\\\git\\\\\\\\Git.exe\\" 在 BuildInterfaces.Build 中的参数字符串中转义 @LeviLu-MSFT 我将完整传递的参数添加到我的问题中。是否有一个通用的regex 来创建转义的管道参数字符串以由 YAML 管道 正确解释? 【参考方案1】:

我可以使用String.raw方法成功传递带有“和”的参数字符串。见下文:

let ps = String.raw `"Inventory":"---\n  all: \n    hosts: \n      PTC-BLD-ADA5: \n        ansible_user: \"PTC-SVC-ADS-AGT\"\n        ansible_password: \"AgentPW2019\"\n        ansible_port: 5986\n        ansible_connection: \"winrm\"\n        ansible_winrm_transport: \"ntlm\"\n        ansible_winrm_server_cert_validation: \"ignore\"\n","Playbook":"---\n  - \n    hosts: \"all\"\n    gather_facts: true\n    vars: \n      SoftwareFolder: \"ansibleshare\"\n      SoftwareSource: \"/mnt/ SoftwareFolder \"\n      AnsibleRoot: \"D:\\\\Ansible\"\n      Proxy: \"http://www-cache.psitrans.de:3128\"\n    tasks: \n      - \n        name: \"set windows proxy settings\"\n        win_inet_proxy: \n          auto_detect: false\n          proxy: \" Proxy \"\n      - \n        name: \"create directory ansible\"\n        win_file: \n          path: \" AnsibleRoot \"\n          state: \"directory\"\n      - \n        name: \"copy software to target machine\"\n        win_copy: \n          src: \" SoftwareSource \"\n          dest: \" AnsibleRoot \"\n      - \n        name: \"exe install git client\"\n        win_package: \n          path: \" AnsibleRoot \\\\ SoftwareFolder \\\\git\\\\Git.exe\"\n          state: \"present\"\n          product_id: \"git\"\n          creates_path: \"C:\\\\Program Files\\\\Git\\\\cmd\\\\git.exe\"\n          arguments: \n            - \"/SILENT\"\n      - \n        name: \"msi install 7z\"\n        win_package: \n          path: \" AnsibleRoot \\\\ SoftwareFolder \\\\7z\\\\7z.msi\"\n          state: \"present\"\n"`; 
        
let vstsdef : bi.Build = 
        definition:  id: 48 ,
        parameters: ps
       ;
    
let nq = await build.queueBuild(vstsdef,"TestProject")

查看以下来自 yaml 管道的输出:

【讨论】:

以上是关于Azure DevOps YAML 管道从传递的变量中删除引号和双反斜杠的主要内容,如果未能解决你的问题,请参考以下文章

azure devops yaml管道未设置变量

Azure DevOps 中的多个 YAML 构建管道

Azure DevOps - 使用参数在 yaml 管道定义中设置路径触发器

如何在 yaml 中处理 Azure DevOps 管道中的错误?

如何在 Azure DevOps yaml 管道中设置 ENVIRONMENT 状态

Azure DevOps Pipelines - 仅在上一次运行成功时运行 YAML 管道