共享库中的字符串插值'的全局变量



Cloudbees 2.289.1.2

我正在根据Jenkinsfile字符串插值准则更改代码。注意:我知道GroovyString插值需要包含变量的双引号。

共享库中的几个全局变量(vars/下)中有几个sh。

目前(没有使用Jenkins的String插值指令),下面指定的命令会发出警告(显示在每个命令之后)。

第一个命令:此命令无法填充自定义/用户定义的变量,但似乎填充了用户名和密码:

String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}"
.toLowerCase()
// tag images
withCredentials([usernamePassword(
credentialsId: pushCredentialsId,
passwordVariable: 'password',
usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
sh 'set +x skopeo copy docker://$resultingImage:latest docker://$resultingImage:$tagName --src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo "done copying ${resultingImage}:${tagName}"'
}
}

输出:

[Pipeline] withCredentials
Masking supported pattern matches of $username or $password
[Pipeline] {
[Pipeline] sh
+ set +x skopeo copy docker://:latest docker://: --src-tls-verify=false '--src-creds=****:****' '--dest-creds=****:****' echo 'done copying :'

如果使用双引号,则会显示以下警告,但命令的格式正确:

[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [password, username]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ set +x

第二个命令:这会引发一个错误(似乎凭据检索正确),无论我是否使用"${chartTarballName}";或${chartTarballName}或$chartTarball Name:

sh 'curl -f -u $username:$password -T "${chartTarballName}" $chartPublishRepo/$chartTarballName'

错误:

[Pipeline] sh
+ curl -f -u ****:**** -T '' /
curl: (3) <url> malformed
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
ERROR: script returned exit code 3

如果使用双引号,则会显示以下警告,但命令的格式正确:

Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [password, username]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ curl -f -u ****:**** -T exp-calculator-0.14.11.tgz https://repository.net/artifactory/stable-local/exp-calculator-0.14.11.tgz

我猜这些插值规则只在声明性管道指令中起作用,而不适用于脚本管道、共享库中的全局变量(至少是用户定义的变量)和其他GroovySSL脚本。

更新-1:

单引号似乎只适用于标准的指令管道指令:

pipeline {
environment {
CUSTOM_ENV_VAR = 'This is an environment variable'
}
agent  any
stages {
stage('build') {
steps {
withCredentials([string(credentialsId: 'sq_token', variable: 'SECRET')]) {
sh ("echo $SECRET")
sh ('echo $SECRET $CUSTOM_ENV_VAR')

script {
String scriptBlockVariable = 'This is a variable in a script block'
sh ('echo $scriptBlockVariable')
sh ('echo $SECRET $scriptBlockVariable')
}
}
}
}
}
}

输出:

[Pipeline] stage
[Pipeline] { (build)
[Pipeline] withCredentials
Masking supported pattern matches of $SECRET
[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
Affected argument(s) used the following variable(s): [SECRET]
See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ echo ****
****
[Pipeline] sh
+ echo **** This is an environment variable
**** This is an environment variable
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ echo
[Pipeline] sh
+ echo ****
****
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
[Pipeline] // stage

试着如下看待它:当您执行一个使用解释器(如shbatpowershell)的作业时,有两个单独的上下文保存执行参数
第一个上下文是实际的groovy代码,它包含代码定义的所有参数,可以是输入参数、全局参数或使用def关键字在代码中定义的任何参数
第二个上下文是将加载到执行运行时环境中的一组参数,每当您运行解释器步骤(shbatpowershell)时,这些步骤都可以使用这些参数作为环境参数。

groovy的字符串插值在第一个上下文中运行,只能访问代码中定义的变量,而shell步骤传递和执行的命令只能访问第二个上下文中的参数。在你的情况下,你将两者混合在一起。

现在,让我们来检查不同的关键字及其范围:
定义参数的简单def语句将使其可用于第一个上下文-groovy代码,从而可用于字符串插值
parameters块在声明性管道中是一个特殊的关键字,它使参数在两个上下文中都可用-它对groovy代码可用,但也作为环境变量加载到shell步骤环境的运行时环境中。它同时支持常规参数和凭据
Scripted pipeline不能使用parameters指令,相反,它们有一个不同的关键字,用于向执行环境中添加参数,称为withEnv:

withEnv-设置块中的一个或多个环境变量。这些可用于该范围内产生的任何外部进程。

withEnv仅支持常规参数,因此引入了另一个支持凭据的关键字:withCredentials,它可以像withEnv步骤一样设置凭据参数。

回到您的问题:

Jenkins确实建议不要对敏感参数使用字符串插值,而是将它们传递到执行环境(context2),并让shell步骤将它们用作环境变量,因此您需要用单引号定义字符串,但另一方面,您希望使用代码中定义的参数(context1),这些参数只能通过需要双引号的字符串插值来计算。因此,您实际上试图同时使用两个上下文中的参数,这有点棘手。

处理这种混合物有两种选择:

1-在withEnv关键字旁边使用withCredentials,使用shell语法参数引用($)定义带单引号的字符串(禁用字符串插值),并让shell从环境变量中提取所有参数。类似于:

String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}".toLowerCase()
// tag images
withCredentials([usernamePassword(credentialsId: pushCredentialsId, passwordVariable: 'password',usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
withEnv(['TAG_NAME=tagName', "IMAGE=${resultingImage}"]) {
sh 'set +x skopeo copy docker://$IMAGE:latest docker://$IMAGE:$TAG_NAME --src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo "done copying $IMAGE:$TAG_NAME"'
}
}
}

2-将命令字符串的创建分为多个部分,每个部分都处理正确的上下文-groovy参数将在创建命令时进行评估,并且shell命令将仅提取相关参数。类似于:

String resultingImage = "${repo}/${parameters.openshiftProject}/${appImageName}".toLowerCase()
// tag images
withCredentials([usernamePassword(credentialsId: pushCredentialsId, passwordVariable: 'password', usernameVariable: 'username')]) {
parameters[IMAGE_TAGS].each { tagName ->
sh 'set +x skopeo copy docker://' + resultingImage + ':latest docker://' + "${resultingImage}:${tagName}" + '--src-tls-verify=false --src-creds=$username:$password --dest-creds=$username:$password echo' + /"done copying ${resultingImage}:${tagName}"/
}
}

这是一篇关于Jenkins环境变量和用法的非常好的文章。

最新更新