Дженкинс - необъяснимый отказ многоотраслевого трубопровода

В своем конвейере я использую методы readJSON и writeJSON на этапе утилиты конвейера плагин для чтения / записи файлов на этапах конвейера. Для обычного конвейера все работает отлично. Однако, когда я создаю «многоотраслевой конвейер», тот же конвейер не работает. Ошибка происходит, когда последующий этап пытается прочитать файл с помощью readJSON, который должен был быть создан на предыдущем этапе. Любопытно следующее: на одном этапе созданный файл был доступен для использования командой (команда aws ecs register-task-definition успешно завершена) НО впоследствии не присутствует в рабочем пространстве /var/jenkins_home/workspace/TestPipeline на узле.

Чтобы сосредоточиться на неудаче, я только вставляю соответствующие этапы конвейера.

stage('RegisterTaskDefinition') {
    agent any
    steps {
        sh 'printenv'
        script {            
            def templateFile = env.TEMPLATE_BASE_PATH +'/' + TASK_DEF_TEMPLATE
            def taskDefinitionTemplate = readJSON(file: templateFile)

            taskDefinitionTemplate.taskRoleArn = env.TASK_ROLE_ARN
            taskDefinitionTemplate.executionRoleArn = env.EXECUTION_ROLE_ARN
            taskDefinitionTemplate.containerDefinitions[0].image = "NewImage"
            taskDefinitionTemplate.containerDefinitions[0].portMappings[0].containerPort = env.APP_PORT.toInteger()

            taskDefFile = env.TEMPLATE_BASE_PATH + '/' + env.TASK_DEFINITION_FILE
            writeJSON(file: taskDefFile, json: taskDefinitionTemplate)

            def registerTaskDefinitionOutput = sh (
            script: "aws ecs register-task-definition --cli-input-json file://${taskDefFile}",
            returnStdout: true
            ).trim()
            echo "Register Task Def result: ${registerTaskDefinitionOutput}"

            def registerTaskDefOutputFile = env.TEMPLATE_BASE_PATH + '/registerTaskDefOutput.json'
            echo "********************************"
            sh 'pwd'
            writeJSON(file: registerTaskDefOutputFile, json: registerTaskDefinitionOutput, pretty: 2)
            echo "********************************${registerTaskDefOutputFile}"
        }
    }
}
stage('CreateTaskSet') {
    agent any
    steps{
        script{
            def registerTaskDefOutputFile = env.TEMPLATE_BASE_PATH + '/' + env.REGISTER_TASK_DEF_OUTPUT
            def taskSetTemplateFile = env.TEMPLATE_BASE_PATH + '/' + env.TASK_SET_TEMPLATE_FILE
            def taskSetFile = env.TEMPLATE_BASE_PATH + '/' + env.TASK_SET_FILE

            def registerTaskDefinitionOutput = readJSON(file: registerTaskDefOutputFile)
            def taskSetTemplateJson = readJSON(file: taskSetTemplateFile)

            taskSetTemplateJson.taskDefinition = registerTaskDefinitionOutput.taskDefinition.taskDefinitionArn
            taskSetTemplateJson.loadBalancers[0].containerPort = env.APP_PORT.toInteger()
            taskSetTemplateJson.loadBalancers[0].targetGroupArn = targetGroupArn

            writeJSON(file: taskSetFile, json: taskSetTemplateJson, pretty: 2)
        }
    }
}

Чтобы уточнить, этап RegisterTaskDefinition завершается успешно, а этап CreateTaskSet - сбой.

Сгенерированное исключение:

java.io.FileNotFoundException: /var/jenkins_home/workspace/TestPipeline/infrastructure/registerTaskDefOutput.json does not exist.
    at org.jenkinsci.plugins.pipeline.utility.steps.json.ReadJSONStepExecution.doRun(ReadJSONStepExecution.java:82)
    at org.jenkinsci.plugins.pipeline.utility.steps.AbstractFileOrTextStepExecution.run(AbstractFileOrTextStepExecution.java:32)
    at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

У меня следующие вопросы:

  1. Чем объясняется разница в поведении между двумя типами трубопроводов?
  2. Для обычного конвейера я могу видеть файлы, созданные конвейером, в /var/jenkins_home/workspace/TestPipeline на узле. Для «многоотраслевого трубопровода» это не так. Какой каталог использует Дженкинс для «многоотраслевого конвейера»?
  3. Какие журналы помогут мне диагностировать проблему?

Я не могу найти никакой документации, объясняющей эту разницу в поведении двух типов конвейеров. Буду признателен за любые предложения.


person Umair Ishaq    schedule 23.05.2020    source источник


Ответы (1)


Из вашего кода:

stage('RegisterTaskDefinition') {
    agent any

а также

stage('CreateTaskSet') {
    agent any

Вполне возможно, что эти два этапа выполняются на разных агентах, поскольку вы сказали Дженкинсу, что хотите, чтобы случайный агент запускал первый этап и случайный агент для запуска второго этапа. Эти агенты могли быть такими же ранее; однако требований нет, они будут такими же.

Чтобы этого не произошло, выделите узел заранее и не меняйте его:

pipeline {
   agent any
   stage('1') { ... }
   stage('2') { ... }
}

Это гарантирует, что оба этапа будут выполняться на одном агенте, поэтому результаты, записанные на первом этапе в ${env.WORKSPACE}, будут доступны для второго.

person MaratC    schedule 23.05.2020
comment
Я понимаю вашу точку зрения, и она полностью верна. Однако в этом случае я запускаю Jenkins в Docker, и есть только один агент. Я попробую вашу технику и обновлю свои выводы. Спасибо. - person Umair Ishaq; 23.05.2020
comment
Попробуйте echo env.WORKSPACE в начале обоих этапов, чтобы убедиться, что они одинаковы. - person MaratC; 23.05.2020
comment
Ты прав. После удаления директивы agent any конвейер работает. Кажется, он проверяет новую копию репо на обоих этапах, когда agent any присутствует на этапе. НО это происходит только для многоотраслевого конвейера. Это действительно указывает на разницу в поведении между двумя конвейерами. Ожидается ли это? - person Umair Ishaq; 24.05.2020
comment
Выделение агента также означает выделение рабочего пространства. Я могу предположить, что в многоотраслевом варианте он может выделять один раз для каждой ветки, чтобы учесть ситуации, когда две разные ветки одновременно работают на одном и том же узле. В одной ветке этого не происходит. - person MaratC; 25.05.2020
comment
Если мой ответ работает для вас, пожалуйста, не забудьте проголосовать и пометить его как принятый, чтобы другие люди могли его использовать. Спасибо! - person MaratC; 25.05.2020
comment
Спасибо за ответ, @MaratC. Я надеялся узнать что-то из своего вопроса, в частности, есть ли какие-либо журналы, которые указали бы, что происходит. Ваше предложение помогло решить проблему, но у меня нет конкретных ответов на свои вопросы. Приму твой ответ, если других ответов не увижу. - person Umair Ishaq; 02.06.2020