我正在构建一个 Jenkins 管道,用于在远程数据中心内使用特定的 Jenkins 代理将我的代码部署到这些数据中心的场景。这是由于一些端口的防火墙限制,特别是WinRM在我们的一些全球数据中心之间被阻止。
我们的部署是这样编写的,即单个deploy
阶段可以部署到用户传入参数指定的任意数量的环境中。阶段在环境中循环,并为每个环境调用通用部署脚本。
我知道如何在阶段定义中通过其标签或其他闭包来指定代理:
stage ('a stage') {
agent { label 'some agent label' }
steps { ...
但在这种情况下,我正在解决在一个部署阶段部署到多个环境的问题,每个环境都需要自己的代理。
当然,我可以为每个env指定一个唯一的stage,并在适当的时候使用< code>when子句来运行它,但是这很麻烦。
我想做的是告诉管道在部署阶段内部的部署阶段使用什么代理,并能够在该单个阶段中使用多个代理,根据运行的参数动态确定。
答案可能不适合您的所有需求,但动态生成阶段,在此基础上,您可以通过以下方式分配/执行生成阶段。
def agents = ['master', 'agent1', 'agent2']
def generateStage(nodeLabel) {
return {
stage("Runs on ${nodeLabel}") {
node(nodeLabel) {
echo "Running on ${nodeLabel}"
}
}
}
}
def parallelStagesMap = agents.collectEntries {
["${it}" : generateStage(it)]
}
pipeline {
agent none
stages {
stage('non-parallel stage') {
steps {
echo 'This stage will be executed first.'
}
}
stage('parallel stage') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
此外,您可以使用<code>collectEntries</code>,在功能框<code>parallelStagesMap</code〕之外,这样,您可以为不同的阶段使用每个collect条目,并可以动态分配阶段中的节点,在函数<code>generateStage</code>中,您需要根据需要进行修改。
如果要按顺序执行这些阶段,请从脚本中删除并行
。生成阶段
包含返回
,如果没有它,管道将无法按预期工作。
我最初在SO上找到了这个答案,这给了我在舞台内获取节点的想法,而不是使用agent
声明。它没有显示在script
块中的获取,但我最初是这样读的,这给了我尝试在script
中获取节点的想法。一旦你到了那里,尝试在循环中完成它是一个小小的飞跃。
为了证明这一点,我从代理打印了一些局部环境变量来证明我们正在交换代理,在舞台内部,在循环内部。我还向每个代理传递一个文件,以证明我可以通过防火墙传递文件。
请注意,为了连接到防火墙后面的代理,我们必须打开 Jenkins 全局安全配置中定义的端口,从控制器(也称为主节点)入站到代理,以及 https (443) 出站到控制器。入站端口配置为静态端口。
pipeline {
agent none
stages {
stage ('init') {
agent any
steps {
writeFile file: 'tester', text: 'i am a test file'
stash includes: 'tester', name: 'tester'
}
}
stage ('get agents') {
steps {
script {
['Agent1', 'Agent2'].each { agent ->
node (agent) {
echo "I am agent `${NODE_NAME}`\nMy labels are `${NODE_LABELS}`"
unstash 'tester'
echo "the content of the file is `${readFile 'tester'}`"
}
}
}
}
}
}
}
哪些输出:
Started by user Maximilian Cascone Admin
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] stage
[Pipeline] { (init)
[Pipeline] node
Running on Agent1 in /mnt/data/jenkins/workspace/Sandbox/mcascone/dynamic-agents
[Pipeline] {
[Pipeline] writeFile
[Pipeline] stash
Stashed 1 file(s)
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (get agents)
[Pipeline] script
[Pipeline] {
[Pipeline] node
Running on Agent2 in D:\workspace\Sandbox\mcascone\dynamic-agents
[Pipeline] {
[Pipeline] echo
I am agent `Agent2`
My labels are `Cider Redgate Windows Worker02 ant chef npm relativity wix`
[Pipeline] unstash
[Pipeline] readFile
[Pipeline] echo
the content of the file is `i am a test file`
[Pipeline] }
[Pipeline] // node
[Pipeline] node
Running on Agent1 in C:\jenkins\workspace\Sandbox\mcascone\dynamic-agents
[Pipeline] {
[Pipeline] echo
I am agent `Agent1`
My labels are `Itar Agent1`
[Pipeline] unstash
[Pipeline] readFile
[Pipeline] echo
the content of the file is `i am a test file`
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS
所以我已经证明了我可以在一个阶段内动态地获得多个代理。下一步将把它提升到一个共享步骤,这样它就可以在没有script
块的情况下被调用,并使管道变得漂亮整洁。但是作为一个POC,这是一个伟大的成就。我不相信我在其他地方见过这个。
我在看威廉姆·菲斯特的关于贝尔曼·福特算法的视频。 他提到有一种方法可以区分负循环中涉及的节点和10:20时从负循环中可到达的节点。在单源最短路径算法中,这两类节点会导致负inf距离。 我想知道如何做到这一点,但我想不通。我谷歌了一下,但谷歌总是让我了解贝尔曼-福特算法的介绍。 简言之,是否有一种方法来区分负循环中的节点和从负循环中可到达的节点?那么,仅仅通过修改贝尔曼-福特算法就可以得到什么呢?
问题内容: 我有下面的代码: 有谁对我如何延迟循环中的每个循环的建议?假设代码在每次迭代完成后等待10秒。我试过了,但没有设法解决。 问题答案: 您可以设置超时时间,以增加代码间隔,如下所示: 因此,第一个立即运行(间隔* 0为0),第二个在十秒钟后运行,依此类推。 您需要在中作为最终参数发送,以便将其值绑定到function参数。否则,尝试访问数组值将超出范围,您将获得。
问题内容: 我需要在声明式管道中启动一组动态测试。为了更好的可视化目的,我想为每个测试创建一个阶段。有办法吗? 创建一个我知道的阶段的唯一方法是: 我已经看到了这个示例,但是我没有使用声明性语法。 问题答案: 使用声明性语法比声明性语法更具灵活性的脚本化语法,即使声明性文档和建议性更多。 例如,可以循环创建阶段:
我正在尝试使用For循环将一个随机整数(0-2)添加到一个变量中指定的次数。我遇到的问题是,循环不是每次循环时都使用一个新的随机数,所以,如果我输入9,我只能得到0、9,或者18。 我希望一个对象返回的键“a”和“b”具有不同的数值。
我有包含在DataFrame中的链接行。 我的逻辑如下
问题内容: 我有想要应用于多个表的代码,而不是简单地复制和替换表名,而是想使用某种循环或游标来简化代码。 我设想设置一个表名数组,并使用索引遍历该列表,检索每个表名,并在适用于我的代码的情况下使用动态SQL散布表名。 据我所知,由于在SQL中没有“数组”构造,因此我不确定这将如何工作。 关于如何解决这个问题的任何想法? 问题答案: 这是一种实现方法:
本节我们探索的主题是迭代与循环。循环通常在计算机编程用用于自动执行重复性任务。 在Python中最常用的迭代形式就是for循环了。for循环允许你迭代出列表中所有的项,迭代出来后你可以做任何你想做的事情。 比如,我们创建了一个列表,并打印出其中所有元素的平方。 >>> for value in [0, 1, 2, 3, 4, 5]: ... print(value * value) ... 0 1
为了便于示例,让我们定义一个玩具自动机类型: 这种结构被设计成通过循环,我们可以将每个想象成一个具有成功和失败转换到其他状态的状态。因此有限自动机必须递归定义。例如,这里是最简单的自动机: 它由1个总是过渡到自身的状态组成。如果我们愿意,我们可以制造更复杂的自动机: 这些不错。但是接受用户输入并构建一个自动机可能会很好。例如,也许可以从过渡矩阵中构建一个。这里有一个天真的实现: 然而,当我们尝试这