转义Jenkinsfile shell中的JSON字符串
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转义Jenkinsfile shell中的JSON字符串相关的知识,希望对你有一定的参考价值。
我试图逃避jenkins文件中的json-string,但是我在线检查的例子有点复杂。
sshagent(credentials: ['keypair'])
sh """
ssh ansible@ansible-server \
'
# vars
src_env="$params.source_env"
dest_env="$params.destination_env"
src_prefix="$params.source_s3_prefix"
dest_prefix="$params.destination_s3_prefix"
region="$region"
ch="$ch"
aws_account="$aws_account"
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-\$ch-\$dest_env \
--task-definition \$td_id \
--region \$region \
--overrides \\\"containerOverrides\\\": [\\\"name\\\": \\\"s3-sync\\\", \\\"environment\\\": [\\\"name\\\": \\\"SRC_ENV\\\", \\\"value\\\": \\\"$$src_env\\\", \\\"name\\\": \\\"DEST_ENV\\\", \\\"value\\\": \\\"$$dest_env\\\", \\\"name\\\": \\\"SRC_PREFIX\\\", \\\"value\\\": \\\"$$src_prefix\\\", \\\"name\\\": \\\"DEST_PREFIX\\\", \\\"value\\\": \\\"$$dest_prefix\\\"]], \\\"taskRoleArn\\\": \\\"arn:aws:iam::$$aws_account:role/$$ch-$$dest_env\\\" \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
所以,问题是逃避以下json字符串:
--overrides \\\"containerOverrides\\\": [\\\"name\\\": \\\"s3-sync\\\", \\\"environment\\\": [\\\"name\\\": \\\"SRC_ENV\\\", \\\"value\\\": \\\"$$src_env\\\", \\\"name\\\": \\\"DEST_ENV\\\", \\\"value\\\": \\\"$$dest_env\\\", \\\"name\\\": \\\"SRC_PREFIX\\\", \\\"value\\\": \\\"$$src_prefix\\\", \\\"name\\\": \\\"DEST_PREFIX\\\", \\\"value\\\": \\\"$$dest_prefix\\\"]], \\\"taskRoleArn\\\": \\\"arn:aws:iam::$$aws_account:role/$$ch-$$dest_env\\\" \
任何帮助表示赞赏我尝试了很多不同的方法,但似乎没有任何工作。
我建议您不要在ssh之后尝试评估所有变量,而是在shell脚本评估中计算shh命令。
在groovy中,当你使用双引号(单引号或三引号)时,任何跟随$
的内容都将被评估/替换。因此,您可以在shell脚本中使用的每个变量前面添加一个$
,并在shell脚本运行之前对变量进行评估。您还需要转义任何您不希望作为字符串处理的一部分进行评估的$
。
特别是对于json blob,我建议在包含覆盖的shell脚本之外创建一个映射,然后将该变量转换为json字符串。这样你就不必担心使用正确数量的\
(尽管你可以在三引号字符串中使用单引号而不转义)并且你的管道文件更具可读性。
这是我写的方式:
sshagent(credentials: ['keypair'])
// ch is defined is defined somewhere in the pipeline
// aws_account is also defined somewhere in the pipeline
def overrides = [
containerOverrides: [
[
environment: [
[
name: "SRC_ENV",
value: params.source_env
],
[
name: "DEST_ENV",
value: params.destination_env
],
[
name: "SRC_PREFIX",
value: params.source_s3_prefix
],
[
name: "DEST_PREFIX",
value: params.destination_s3_prefix
]
],
name: "s3-sync"
]
],
taskRoleArn: "arn:aws:iam::$aws_account:role/$ch-$params.destination_env"
]
sh """
ssh ansible@ansible-server \
'
# Run ECS task
echo "---- Run ECS task ----"
task_id=\$(aws ecs run-task \
--cluster cluster-$ch-$params.destination_env \
--task-definition \$td_id \
--region $region \
--overrides $groovy.json.JsonOutput.toJson(overrides) \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
请注意,我没有转义任何我想要替换字符串处理的变量,我只是转义了
task_id=\$(aws ecs run-task \
这样在运行ssh脚本时运行aws ecs run-task ...
(而不是在评估字符串时)。
基于Vasiliki Siakka的答案,我事先解析了json参数并转义了json字符串中的双引号,以避免它们在ssh命令中被删除。那么,对我有用的解决方案如下:
sshagent(credentials: ['keypair'])
// ch is defined is defined somewhere in the pipeline
// aws_account is also defined somewhere in the pipeline
def overrides = [
containerOverrides: [
[
environment: [
[
name: "SRC_ENV",
value: params.source_env
],
[
name: "DEST_ENV",
value: params.destination_env
],
[
name: "SRC_PREFIX",
value: params.source_s3_prefix
],
[
name: "DEST_PREFIX",
value: params.destination_s3_prefix
]
],
name: "s3-sync"
]
],
taskRoleArn: "arn:aws:iam::$aws_account:role/$ch-$params.destination_env"
]
def parsed_overrides = groovy.json.JsonOutput.toJson(overrides).replace("\"", "\\\"")
sh """
ssh ansible@ansible-server \
'
# Run ECS task
echo "---- Run ECS task ----"
task_id=\$(aws ecs run-task \
--cluster cluster-$ch-$params.destination_env \
--task-definition \$td_id \
--region $region \
--overrides "$parsed_overrides" \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
以上是关于转义Jenkinsfile shell中的JSON字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Jenkinsfile 中使用 package.json 的版本号自动重命名“dist”文件夹