迭代的詹金斯(Jenkins)Groovy地图,具有多套 [英] Iterating Jenkins groovy map, with multiple sets
问题描述
我想通过Jenkins groovy管道寻求帮助,该管道是从此处复制的: 是否可以创建并行Jenkins声明式管道阶段是否处于循环中?
I'd like to ask for help with a a Jenkins groovy pipeline, copied from here: Is it possible to create parallel Jenkins Declarative Pipeline stages in a loop?
我希望在映射下将几个个变量集传递给,在并行运行下几个阶段.但是,只有最后一组(地图底部的方括号)被注册为我的地图.
I'd like for a several sets of vars to be passed in a under a map, for several stages under a parallel run. However, only the last set (square brackets at the bottom of the map) gets registered for my map.
并行阶段运行时,映射成功进行迭代,但仅使用最后一组(当前为install_Stage(it)
)进行迭代,而忽略其他组.这意味着我得到了一个并行显示四个"stage: install ${product}"
阶段的管道,仅此而已.我想按照以下代码,通过四个阶段(网络设置,还原和安装)获得三个并行:
When the parallel stage runs, the map iterates successfully, but only with the last set (currently install_Stage(it)
), ignoring other sets. Meaning that I get a pipeline showing four "stage: install ${product}"
stages in parallel, and that's it. I'd like to get three parallels with four stages (network setup, revert, and install), as per my code below:
#!groovy
@Library('ci_builds')
def products = ["A", "B", "C", "D"]
def parallelStagesMap = products.collectEntries {
switch (it) {
case "A":
static_ip_address = "10.100.100.6"; static_vm_name = "install-vm1"; version = "14.1.60"
break
case "B":
static_ip_address = "10.100.100.7"; static_vm_name = "install-vm2"; version = "15.1"
break
case "C":
static_ip_address = "10.100.100.8"; static_vm_name = "install-vm3"; version = "15.1"
break
case "D":
static_ip_address = "10.100.100.9"; static_vm_name = "install-vm4"; version = "15.2"
break
default:
static_ip_address = "The product name is not on the switch list - please enter an ip address"
version = "The product name is not on the switch list - please enter a version"
break
}
["${it}" : network_reg(it)]
["${it}" : revert_to_snapshot_Stage(it)]
["${it}" : install_Stage(it)]
}
def network_reg(product) {
return {
stage("stage: setup network for ${product}") {
echo "setting network on ${static_vm_name} with ${static_ip_address}."
sh script: "sleep 15"
}
}
}
def revert_to_snapshot_Stage(product) {
return {
stage("stage: revert ${product}") {
echo "reverting ${static_vm_name} for ${product} on ${static_ip_address}."
sh script: "sleep 15"
}
}
}
def install_Stage(product) {
return {
stage("stage: install ${product}") {
echo "installing ${product} on ${static_ip_address}."
sh script: "sleep 15"
}
}
}
pipeline {
agent any
stages {
stage('non-parallel env check') {
steps {
echo 'This stage will be executed first.'
}
}
stage('parallel stage') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
network_reg和revert_to_snapshot_Stage无法运行(除非我将它们放置为最后一组而不是["$ {it}":install_Stage(it)]),在这种情况下,同样,只有并行阶段之一是运行)
The network_reg and revert_to_snapshot_Stage won't run (unless I place them as the last set instead of ["${it}" : install_Stage(it)] , in which case, again, only the one of the parallel stages is run)
I don't mind a different approach to run several map definitions, but others such as: How to define and iterate over map in Jenkinsfile don't allow for a full multi variable map (more than a key+value pair)
任何帮助将不胜感激,谢谢!
Any help would be appreciated, Thanks!
推荐答案
我假设您遇到类似的问题,就像我试图动态构建用于并行执行的并行分支一样.
I assume you have a similar issue like I had trying to dynamically build the parallel branches for parallel execution.
两件事非常重要:
-
制作循环变量的副本(在您的情况下为
it
),并仅在并行分支内使用该副本;如果您不这样做,那么所有分支(闭包)都将引用相同的变量,而该变量当然具有相同的值.这对于闭包而言尤其如此.另请参阅: http://groovy-lang.org/closures.html .
Make a copy of the loop variable (in you case:
it
) and use that copy only inside the parallel branch; if you don't all branches (closures) will reference the very same variable which of course will have the same value. That is particular to closures. See also: http://groovy-lang.org/closures.html.
请勿使用collectEntries{}
.坚持使用Java风格的循环,因为通常情况下,groovy循环无法正常工作.某些.each{}
构造可能已经起作用,但是如果有疑问,请切换到Java循环.另请参见:无法使用进行地图迭代Jenkins Pipeline中的Groovy
Don't use collectEntries{}
. Stick to the java-style loops as groovy loops most of the time do not work properly. Some .each{}
constructs may work already but if in doubt switch to the java loops. See also: Impossibility to iterate over a Map using Groovy within Jenkins Pipeline
下面的示例对我有用.我相信您将能够根据需要进行调整.
Following stripped down example works for me. I believe you'll be able to adjust it to your needs.
def products = ["A", "B", "C", "D"]
def parallelStagesMap = [:]
// use java-style loop
for (def product: products) {
// make a copy to ensure that each closure will get it's own variable
def copyOfProduct = product
parallelStagesMap[product] = {echo "install_Stage($copyOfProduct)"}
}
echo parallelStagesMap.toString()
pipeline {
agent any
stages {
stage('parallel stage') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
- 如果仍然不起作用:检查是否存在并升级您的
Pipeline: Groovy
插件,因为它们通常可以解决很多问题,这些问题通常在常规中有效,但不会在管道中使用.
- If it still doesn't work: Check whether there's and upgrade your
Pipeline: Groovy
plugin as they usually fix lot of issues which usually work in groovy but won`t in pipeline.
您可能想检查以下相关问题,其中也包含一个最小示例: 使用常规的CPS封闭进行并行执行
You may want to check following related question which contains a minimal example as well: Currying groovy CPS closure for parallel execution
这篇关于迭代的詹金斯(Jenkins)Groovy地图,具有多套的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!