gpt4 book ai didi

jenkins - Ansible 无法读取 Jenkins 多行参数传递的带有空格的文件名

转载 作者:行者123 更新时间:2023-12-05 01:50:05 31 4
gpt4 key购买 nike

Ansible 代码工作正常,并且当传递的文件名没有空格时能够逐行读取。

问题是当 Jenkins 在 source_file 参数中传递包含空格的文件名时,如下所示。

enter image description here

以下是 ansible 的调用方式:

sh "ansible-playbook -i /web/playbooks/filecopy/allmwhosts.hosts /web/playbooks/filecopy/copyfiles.yml -e source_host=$source_host -e '{ source_file: $source_file }'

[Pipeline] sh (hide)
+ ansible-playbook -i /web/filecopy/allmwhosts.hosts /web/playbooks/filecopy/copyfiles.yml -e source_host=usurb31as30v -e '{ source_file: /web/lib/hello.txt
/web/lib/Policy Form_LifeAgents_new.pdf
/web/lib/Policy Form_LifeAgents_old.pdf }'

下面的 Ansible 代码:

   - debug:
msg: "FILES: {{ files_list }}"

- debug:
msg: "The NEWLINE files are {{ item }}"
with_items:
- "{{ source_file.split() }}"

- debug:
msg: "The NEWLINE1 files are {{ item }}"
with_items:
- "{{ source_file.splitlines() }}"

- set_fact:
source_file_new: "{{ item | quote + '\n' + source_file | default() }}"
with_items:
- "{{ source_file.split('\n') }}"

- debug:
msg: "AFTER QUOTE: {{ source_file_new }}"


- debug:
msg: "QUOTED NEWLINE files are {{ item }}"
with_items:
- "{{ source_file_new.split('\n') }}"

输出:

TASK [debug] *******************************************************************
task path: /web/playbooks/filecopy/copyfiles.yml:18
Saturday 20 August 2022 22:59:50 -0500 (0:00:00.077) 0:00:00.118 *******
ok: [localhost] => {
"msg": "FILES: /web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf"
}

TASK [debug] *******************************************************************
task path: /web/playbooks/filecopy/copyfiles.yml:21
Saturday 20 August 2022 22:59:50 -0500 (0:00:00.032) 0:00:00.150 *******
ok: [localhost] => (item=/web/lib/hello.txt) => {
"msg": "The NEWLINE files are /web/lib/hello.txt"
}
ok: [localhost] => (item=/web/lib/Policy) => {
"msg": "The NEWLINE files are /web/lib/Policy"
}
ok: [localhost] => (item=Form_LifeAgents_new.pdf) => {
"msg": "The NEWLINE files are Form_LifeAgents_new.pdf"
}
ok: [localhost] => (item=/web/lib/Policy) => {
"msg": "The NEWLINE files are /web/lib/Policy"
}
ok: [localhost] => (item=Form_LifeAgents_old.pdf) => {
"msg": "The NEWLINE files are Form_LifeAgents_old.pdf"
}

TASK [debug] *******************************************************************
task path: /web/playbooks/filecopy/copyfiles.yml:21
Sunday 21 August 2022 12:16:24 -0500 (0:00:00.021) 0:00:00.101 *********
ok: [localhost] => (item=/web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf /web/lib/Policy Specimen_MLA_Everest_new.pdf /web/lib/Policy Specimen_MLA_Everest_old.pdf) => {
"msg": "The NEWLINE1 files are /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf /web/lib/Policy Specimen_MLA_Everest_new.pdf /web/lib/Policy Specimen_MLA_Everest_old.pdf"
}

TASK [set_fact] ****************************************************************
task path: /web/playbooks/filecopy/copyfiles.yml:26
Saturday 20 August 2022 22:59:50 -0500 (0:00:00.069) 0:00:00.219 *******
ok: [localhost] => (item=/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf) => {
"ansible_facts": {
"source_file_new": "'/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf'\n/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf"
},
"ansible_loop_var": "item",
"changed": false,
"item": "/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf"
}

TASK [debug] *******************************************************************
task path: /web/playbooks/filecopy/copyfiles.yml:31
Saturday 20 August 2022 22:59:50 -0500 (0:00:00.080) 0:00:00.300 *******
ok: [localhost] => {
"msg": "AFTER QUOTE: '/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf'\n/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf"
}

TASK [debug] *******************************************************************
task path: /web/playbooks/filecopy/copyfiles.yml:35
Saturday 20 August 2022 22:59:50 -0500 (0:00:00.031) 0:00:00.331 *******
ok: [localhost] => (item='/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf') => {
"msg": "QUOTED NEWLINE files are '/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf'"
}
ok: [localhost] => (item=/web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf) => {
"msg": "QUOTED NEWLINE files are /web/lib/hello.txt /web/lib/Policy Form_LifeAgents_new.pdf /web/lib/Policy Form_LifeAgents_old.pdf"
}

预期 ansible 应该读取三行,但是 split() 或 split('\n') 都没有帮助

最佳答案

您正在通过 shell 启动 Ansible playbook。这里的问题是一个引用问题。 (ba)sh 将新行和空格解释为参数分隔符。因此,您需要正确引用所有内容才能:

  1. (ba)sh 了解 Ansible 的 -e 参数在列表中的最后一个文件之后结束
  2. 可以理解这是一个包含换行符和空格的单个字符串。

一旦解决了这个问题,其余的处理就变得微不足道了,因为您只需 source_file.splitlines() 您的值即可获取单个文件的列表。

请注意,Jenkins 有一个 Ansible 插件,可以在这种情况下简化您在 gui 上的生活。如果您添加“调用 ansible playbook”构建步骤并单击“高级”,则只需输入键名称和值(可以是变量)即可添加额外的变量。启 Action 业时,您可以在结果中看到正确的安全引用。

不幸的是,这个方便的帮助在管道语法帮助器中不可用,您还必须自己构建额外参数的字符串。

长话短说:这就是您的 shell 脚本命令应该如何编写,以安全地引用所有 ansible 参数:

ansible-playbook -i /web/playbooks/filecopy/allmwhosts.hosts \
/web/playbooks/filecopy/copyfiles.yml \
-e "source_host='$source_host'" \
-e "source_file='$source_file'"

作为概念证明,这里是一个一体化演示声明式 Jenkins 管道,您可以将其粘贴到管道作业中,并通过 shell 和 Ansible 插件成功运行声明的 playbook。

请注意,由于我在管道内声明了作业参数,因此第一次构建将系统性地失败。您只能在第二次构建时以交互方式提供参数。默认值应该足以重现您问题中描述的情况。

pipeline {
agent any

stages {
stage('Setup parameters') {
steps {
script {
properties([
parameters([
text(
defaultValue: "/a/file\n/an/other file\n/one/more/file",
description: "Enter absolute path of files on target one on each line",
name: "source_file"
)
])
])
}
}
}

stage('Create playbook') {
steps {
sh '''
cat <<"EOF" > playbook.yml
---
- hosts: localhost
gather_facts: false

vars:
file_list: "{{ source_file.splitlines() }}"

tasks:
- name: Show content of processed incoming extra var
debug:
var: file_list

- name: Just proove it works
debug:
msg: "received individual file {{ item }}"
loop: "{{ file_list }}"
EOF
'''
}
}

stage('Run playbook through shell'){
steps {
sh '''
ansible-playbook playbook.yml -e "source_file='$source_file'"
'''
}
}

stage('Run playbook through ansible plugin'){
steps {
ansiblePlaybook extras: '-e "source_file=\'$source_file\'"', playbook: 'playbook.yml'
}
}
}
}

这给出了(第二次运行并使用默认值):

Started by user Olivier Clavel
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/testpipe
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Setup parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] properties
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Create playbook)
[Pipeline] sh
+ cat
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Run playbook through shell)
[Pipeline] sh
+ ansible-playbook playbook.yml -e source_file='/a/file
/an/other file
/one/more/file'
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [Show content of processed incoming extra var] ****************************
ok: [localhost] => {
"file_list": [
"/a/file",
"/an/other file",
"/one/more/file"
]
}

TASK [Just proove it works] ****************************************************
ok: [localhost] => (item=/a/file) => {
"msg": "received individual file /a/file"
}
ok: [localhost] => (item=/an/other file) => {
"msg": "received individual file /an/other file"
}
ok: [localhost] => (item=/one/more/file) => {
"msg": "received individual file /one/more/file"
}

PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Run playbook through ansible plugin)
[Pipeline] ansiblePlaybook
[testpipe] $ ansible-playbook playbook.yml -e "source_file='/a/file
/an/other file
/one/more/file'"
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [Show content of processed incoming extra var] ****************************
ok: [localhost] => {
"file_list": [
"/a/file",
"/an/other file",
"/one/more/file"
]
}

TASK [Just proove it works] ****************************************************
ok: [localhost] => (item=/a/file) => {
"msg": "received individual file /a/file"
}
ok: [localhost] => (item=/an/other file) => {
"msg": "received individual file /an/other file"
}
ok: [localhost] => (item=/one/more/file) => {
"msg": "received individual file /one/more/file"
}

PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

关于jenkins - Ansible 无法读取 Jenkins 多行参数传递的带有空格的文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73431604/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com