groovy 变量在并行阶段被覆盖

oymdgrw7  于 2022-11-01  发布在  其他
关注(0)|答案(1)|浏览(232)

在我维护的一个项目的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_FILESOME_VARIABLE将始终显示为在agent_2阶段中设置的值。

z9ju0rcb

z9ju0rcb1#

您的问题似乎是如何声明变量。为了明确地告诉groovy创建一个新变量,您需要使用def。因此,如果您在创建变量时没有添加def,它可能会在当前脚本的绑定中结束,groovy可能会将它们视为全局变量。因此,请尝试如下所示更改变量声明。

def ANSIBLE_CREDENTIALS = "ansible_user=$NODE_USERNAME ansible_ssh_pass=$NODE_PASSWORD ansible_sudo_pass=$NODE_PASSWORD"

相关问题