本文介绍了Azure DevOps YAML管道从传递的变量中删除引号和双反斜杠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个管道,期望Ansible-Playbook作为队列时间( string )上的传递变量.将经典管道转换为YAML后,我认识到Playbook-String中的行情丢失了.

I have a Pipeline that expect a Ansible-Playbook as passed variable on queue-time (string). After converting my classic Pipeline to YAML I recognize that Quotes in the Playbook-String are missing.

---
  -
    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管道通过了剧本(" )

---
  -
    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}'),但这无济于事.

行情是Playbooks的重要组成部分,我敢肯定,原因有很多,为什么管道会像这样.但是,作为利益相关者,当通过传递变量来更改变量时,这是一件很糟糕的事情,而且,在经典的Pipelines中,不需要这样做.

Quotes are an essential component of Playbooks, I'm pretty sure there are reasons, why the pipeline behave like that. But as a stakeholder, it is feel bad when a variable get changed by passing it and also, in classic Pipelines was no need to do that.

我该如何解决?

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


修改1

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


EDIT 1

Another problem in context of ansible-playbooks is the fact that YAML pipelines also misinterpreting double backslashes \\, which are very important for windows paths in playbooks:

      -
        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管道通过了剧本( \\ )

      -
        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真的很难用于该用例.:(

This makes YAML-Pipelines really hard to use for that use case. :(

# 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

说明

  • 管道将库存 Playbook 接收为 string
  • Bash Task将 string 写入文件并产生我在上面发布的输出(更多是出于调试原因)
  • 可以执行文件
  • Description

    • Pipeline receive Inventory and Playbook as string
    • Bash Task write string into file and produce the output I publish above (more for debug reasons)
    • Ansible execute the files
    • 请记住.经典中的相同管道运行良好:

      Please keep in mind. Same Pipeline in classic runs well:

      我对 queueBuild 函数使用3个参数

      • ``buildOption =见下文
      • projectName = MyProject
      • ignoreWarnings = true
      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'
      

      buildOption作为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 作为对象,如预期的那样.

      My application call the queueBuild function with the buildOption as Object, like expected.

      重要的是要知道,这对于经典管道完全可以正常工作,只有 YAML管道可以对如上所述的传递参数进行更改.

      Important is to know that that works totally fine for classic Pipelines, only YAML Pipelines make changes for the passed parameter descripted like above.

      推荐答案

      我可以通过"和"\"保持使用 String.raw 方法.见下文:

      I can successfully passed the parameter string with " and " \" keeped using String.raw method. See below:

      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管道的输出:

      See below output from yaml pipeline:

      这篇关于Azure DevOps YAML管道从传递的变量中删除引号和双反斜杠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 20:22