web-dev-qa-db-ja.com

宣言的なジェンキンスパイプラインで-エージェントラベルを動的に設定できますか?

プレーン文字列としてではなく、エージェントラベルを動的に設定する方法はありますか?

ジョブには2つの段階があります。

  1. 最初の段階-常に「マスター」エージェントで実行されます。この段階の終わりに、どのエージェントで2番目の段階を実行する必要があるかがわかります。
  2. 第2段階-第1段階で決定したエージェントで実行する必要があります。

私の(動作していない)試みは次のようになります。

pipeline {
    agent { label 'master' }
    stages {
        stage('Stage1') {
            steps {
                script {
                    env.node_name = "my_node_label"
                }
                echo "node_name: ${env.node_name}"
            }
        }

        stage('Stage2') {
            agent { label "${env.node_name}" }
            steps {
                echo "node_name: ${env.node_name}"
            }
        }
    }
}

最初のエコーは正常に機能し、「my_node_label」が出力されます。 2番目のステージは、「my_node_label」というラベルのエージェントでの実行に失敗し、コンソールに次のメッセージが表示されます。

「null」というラベルのノードはありません

多分それが役立つかもしれません-ラベルフィールドに「$ {env}」を入れると、これはJavaクラスであることがわかります:

「org.jenkinsci.plugins.workflow.cps.EnvActionImpl@79c0ce06」というラベルのノードはありません

22

これがどのように機能するかを確認するには、GStringオブジェクトを使用してprintlnを実行し、agentNameの変数を同時に返します。出力から、この行が他のパイプラインコードよりもかなり前に評価されることがわかります。

agentName = "Windows"
agentLabel = "${println 'Right Now the Agent Name is ' + agentName; return agentName}"

pipeline {
    agent none

    stages {
        stage('Prep') {
            steps {
                script {
                    agentName = "Linux"
                }
            }
        }
        stage('Checking') {
            steps {
                script {
                    println agentLabel
                    println agentName
                }
            }
        }
        stage('Final') {
            agent { label agentLabel }

            steps {
                script {
                    println agentLabel
                    println agentName
                }
            }
    }

    }
}

コンソール出力(このインスタンスには実際にはWindowsというラベルの付いたノードがないため、見つからなかったため中止しました):

Started by user Admin
[Pipeline] echo
Right Now the Agent Name is Windows
[Pipeline] stage
[Pipeline] { (Prep)
[Pipeline] script
[Pipeline] {
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Checking)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Windows
[Pipeline] echo
Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Final)
[Pipeline] node
Still waiting to schedule task
There are no nodes with the label ‘Windows’
Aborted by Admin
[Pipeline] // node
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
ERROR: Queue task was cancelled
Finished: ABORTED

Right Now the Agent Name is Windowsが出力の非常に早い段階で表示されることに注意してください。これはなぜあなたの値がnullであるかを説明しています。そのステートメントは、スクリプトが変数を変更するずっと前に評価されます。

遅延変数GStringを使用して、後で変数を取得しようとする場合があります。

agentLabel = "${-> println 'Right Now the Agent Name is ' + agentName; return agentName}"

残念ながら、これはString型を予期しているため、エラーをスローします。どうやら、レイジーでないGStringをそれ自体でStringに強制することができますが、レイジーバージョンではありません。したがって、もちろん、強制的にStringに強制すると、その時点で変数が評価されます(これは、パイプラインコードが実際に実行される前です)。

agent { label agentLabel as String }

古いノード割り当て方法にフォールバックすることにより、問題を解決できます。

agentName = "Windows"
agentLabel = "${-> println 'Right Now the Agent Name is ' + agentName; return agentName}"

pipeline {
    agent none

    stages {
        stage('Prep') {
            steps {
                script {
                    agentName = "Linux"
                }
            }
        }
        stage('Checking') {
            steps {
                script {
                    println agentLabel
                    println agentName
                }
            }
        }
        stage('Final') {

            steps {
                node( agentLabel as String ) {  // Evaluate the node label later
                    echo "TEST"
                }
                script {
                    println agentLabel
                    println agentName
                }
            }
        }
    }
}

このコンソール出力から、Linuxノードが適切に検出され、パイプラインが終了したことがわかります。 agentName == Windowsの初期評価は決して起こりません:

Started by user Admin
[Pipeline] stage
[Pipeline] { (Prep)
[Pipeline] script
[Pipeline] {
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Checking)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Right Now the Agent Name is Linux
[Pipeline] echo
Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Final)
[Pipeline] echo
Right Now the Agent Name is Linux
[Pipeline] node
Running on Slave 1 in /home/jenkinsslave/jenkins/workspace/test
[Pipeline] {
[Pipeline] echo
TEST
[Pipeline] }
[Pipeline] // node
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Right Now the Agent Name is Linux
[Pipeline] echo
Linux
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS

これはおそらく、怠zyなGStringとタイプ強制なしで機能しますが、私はそれを試しませんでした。

12
Rob Hales

スクリプトと宣言型のパイプラインを組み合わせてください。まず、スクリプト構文を使用して、たとえば自分がいるブランチを見つけました。次に、AGENT_LABEL変数を定義します。この変数は、宣言パイプラインに沿ってどこでも使用できます

def AGENT_LABEL = null

node('master') {
  stage('Checkout and set agent'){
     checkout scm
     ### Or just use any other approach to figure out agent label: read file, etc
     if (env.BRANCH_NAME == 'master') {
        AGENT_LABEL = "prod"
     } else {
        AGENT_LABEL = "dev"
     }
   }
}

pipeline {
    agent {
       label "${AGENT_LABEL}"
    }

    stages {
        stage('Normal build') {
           steps {
              echo "Running in ${AGENT_LABEL}"
              sh "hostname"
           }
        } 

        stage ("Docker build") {
           agent{
             dockerfile {
                dir 'Dockerfiles'
                label "${AGENT_LABEL}"
             }
            }
            steps{
                sh "hostname"
            }
        }
    }
}
16
Vitaly

スクリプトブロックのコンテキストに関する何かかもしれません。

これは、第2段階で「docker」のラベルを使用して機能します。

def hotLabel = 'docker'

pipeline {
    agent { label 'master' }
    stages {
        stage('Stage1') {
            steps {
                echo "node_name: ${hotLabel}"
            }
        }

        stage('Stage2') {
            agent { label "${hotLabel}" }
            steps {
                echo "node_name: ${hotLabel}"
            }
        }
    }
}

これは同じではありません(ラベル「null」エラーのノードはありません):

def hotLabel = null

pipeline {
    agent { label 'master' }
    stages {
        stage('Stage1') {
            steps {
                script {
                    hotLabel = "docker"
                }
            }
        }

        stage('Stage2') {
            agent { label "${hotLabel}" }
            steps {
                echo "node_name: ${hotLabel}"
            }
        }
    }
}
3
burnettk

これは私のために働いた:

env.agentName = ""

branch_name = "10.1.0"
pipeline {
    agent none

    stages {
        stage('Prep') {
            steps {
                script {
                    println branch_name
                    if ("${branch_name}" == "9.2.0") {
                        env.agentName = "9.2agent"
                    } else {
                        env.agentName = "10.1agent"
                    }
                }
            }
        }

        stage('Finish') {
            steps {
                node (agentName as String) { println env.agentName }
                script {
                    println agentName
                }
            }
        }

    }
}

Output:
SuccessConsole Output
Started by user build
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] stage
[Pipeline] { (Prep)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
10.1.0
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Finish)
[Pipeline] node
Running on 10.1agent in /home/build/jenkins/workspace/testlabel
[Pipeline] {
[Pipeline] echo
rbreg6
[Pipeline] }
[Pipeline] // node
[Pipeline] script
[Pipeline] {
[Pipeline] echo
rbreg6
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS

Changing the branch name to 9.2.0:
Started by user build
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] stage
[Pipeline] { (Prep)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
9.2.0
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Finish)
[Pipeline] node
Running on 9.2agent in /shared/build/workspace/testlabel
[Pipeline] {
[Pipeline] echo
rbregistry
[Pipeline] }
[Pipeline] // node
[Pipeline] script
[Pipeline] {
[Pipeline] echo
rbregistry
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS
2
Susan

変数を動的に注入するために、パラメーター化されたジョブから生じるワークフローが必要でした。次のソリューションは、インライン文字列操作を使用するだけでうまく機能することがわかりました。

String Parameter

pipeline {

   agent { label 'LBL && '+nodeLabel }
   ...
}
2
jxramos