在我维护的一个项目的CI中,需要针对多个体系结构测试代码。然后,我们的Jenkins CI使用一个并行阶段在多个代理上运行。
禁止仿真架构。
在我决定重构管道以使其更清晰之前,一切都运行得很好。我在每个代理上循环的脚本中引入了变量的定义。
我观察到一些奇怪的行为,在一些任务中,这些变量被一个并行的任务覆盖,就好像这些变量有一个全局作用域一样。有没有办法让这些变量对于单个代理的执行完全是局部的?
下面是一段要重现的代码:
def testAgents = ["agent_1", "agent_2"]
def generateTestStage(nodeLabel) {
return {
stage("Tests on ${nodeLabel}") {
node(nodeLabel) {
withCredentials(
[usernamePassword(
credentialsId: "${NODE_NAME}",
usernameVariable: "NODE_USERNAME",
passwordVariable: "NODE_PASSWORD"
)]
){
script {
sh "echo ${nodeLabel}"
ANSIBLE_CREDENTIALS = "ansible_user=$NODE_USERNAME ansible_ssh_pass=$NODE_PASSWORD ansible_sudo_pass=$NODE_PASSWORD"
if (nodeLabel == "agent_1") {
echo "Where am I ? agent_1"
SOME_VARIABLE = "on agent_1"
HOSTS_FILE = "ansible/hosts.template.agent_1.yml"
sh "sleep 3"
} else {
echo "Where am I ? agent_2"
sh "sleep 2"
SOME_VARIABLE = "on agent_2"
HOSTS_FILE = "ansible/hosts.template.agent_2.yml"
}
sh "echo 'BEFORE SLEEP on ${nodeLabel}/${NODE_NAME}: SOME_VARIABLE ${SOME_VARIABLE}'"
sh "echo 'BEFORE SLEEP on ${nodeLabel}/${NODE_NAME}: ANSIBLE_CREDENTIALS ${ANSIBLE_CREDENTIALS}'"
sh "echo 'BEFORE SLEEP on ${nodeLabel}/${NODE_NAME}: HOSTS_FILE ${HOSTS_FILE}'"
sh "echo 'BEFORE SLEEP on ${nodeLabel}/${NODE_NAME}: NODE_USERNAME ${NODE_USERNAME}'"
sh "sleep 10"
sh "echo 'AFTER SLEEP on ${nodeLabel}/${NODE_NAME}: SOME_VARIABLE ${SOME_VARIABLE}'"
sh "echo 'AFTER SLEEP on ${nodeLabel}/${NODE_NAME}: ANSIBLE_CREDENTIALS ${ANSIBLE_CREDENTIALS}'"
sh "echo 'AFTER SLEEP on ${nodeLabel}/${NODE_NAME}: HOSTS_FILE ${HOSTS_FILE}'"
sh "echo 'AFTER SLEEP on ${nodeLabel}/${NODE_NAME}: NODE_USERNAME ${NODE_USERNAME}'"
}
}
}
}
}
}
def parallelTestStages = testAgents.collectEntries {
["${it}" : generateTestStage(it)]
}
pipeline {
environment {
PROJECT = "test"
}
agent none
stages {
stage("Testing on both agents") {
steps {
script {
parallel parallelTestStages
}
}
}
}
}
在这里,NODE_USERNAME
会给出正确的结果,但ANSIBLE_CREDENTIALS
将始终给出最慢代理的凭据,并且HOSTS_FILE
和SOME_VARIABLE
将始终显示为在agent_2
阶段中设置的值。
1条答案
按热度按时间z9ju0rcb1#
您的问题似乎是如何声明变量。为了明确地告诉groovy创建一个新变量,您需要使用
def
。因此,如果您在创建变量时没有添加def
,它可能会在当前脚本的绑定中结束,groovy可能会将它们视为全局变量。因此,请尝试如下所示更改变量声明。