Вызовите этап повторно из другого этапа - PullRequest
0 голосов
/ 24 октября 2019

В настоящее время я пишу задание, которое клонирует исходные образы докеров в мое внутреннее репозиторий докеров. Моя страница параметров работы выглядит следующим образом:

enter image description here

Таким образом, он берет все изображения и затем генерирует фактический путь к тому, как он должен выглядеть

pipeline {
    agent none
    stages {
        stage('Create new image paths:tag'){
            steps {
                script {
                    params.IMAGES.split("\\r?\\n").each{ oldfullPath ->
                        def (path, tag) = oldfullPath.tokenize( ':' )
                        def app = path.tokenize('/')[-1]
                        println "App is ${app} and Tag is ${tag}"
                        switch(params.REPO) {
                            case "monitoring":
                                image = "eu.gcr.io/<PROJECT>/infra/monitoring"
                                break
                            case "apps":
                                image = "eu.gcr.io/<PROJECT>/infra/apps"
                                break
                        }
                        def newFullPath = "${image}/${app}:${tag}"
                        println "Full old image path is ${oldfullPath}"
                        println "Full new image path is ${newFullPath}"
                        // Pull and Push Image stage should be called here ! Using `${oldfullPath}` and `${newFullPath}`
                    }
                }
            }
        }

Как вы можете видеть, поскольку у меня есть многострочный ввод, я должен использовать цикл, чтобы пройти каждую строку, получить имя приложения и тег, и, используя switch, я генерирую newpath. Таким образом, для каждой итерации я получаю ${oldfullPath} и ${newfullPath}

Теперь мне нужно вытащить и нажать эти образы докера. Я не хочу использовать dind, поэтому я использую Kaniko. А чтобы тянуть и толкать изображение, я могу использовать что-то вроде этого:

stage('Pull and Push Image') {
    agent {
        label "kaniko"
    }
    steps {
        container(name: 'kaniko', shell: '/busybox/sh') {
            withCredentials([
                string(credentialsId: 'infra', variable: 'PASS')
            ]) {
                withEnv(['PATH+EXTRA=/busybox:/kaniko']) {
                    sh """#!/busybox/sh
                    echo "FROM <OLD-IMAGE-PATH-COMES-HERE>" | \
                    /kaniko/executor \
                        --dockerfile /dev/stdin \
                        --destination <NEW-IMAGE-PATH-COMES-HERE>
                    """
                }
            }
        }
    }
}

Как видите, это совершенно другая стадия. Поэтому я не уверен, как я могу повторно вызвать этап Pull and Push Image с предыдущего этапа. Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 25 октября 2019

Здесь достаточно много для обработки.

Во-первых, если вы просто хотите скопировать образы Docker в свой реестр, это можно сделать следующим образом:

me@vm:~$ docker pull alpine:latest
latest: Pulling from library/alpine
89d9c30c1d48: Pull complete
Digest: sha256:c19173c5ada610a5989151111163d28a67368362762534d8a8121ce95cf2bd5a
Status: Downloaded newer image for alpine:latest
me@vm:~$ docker tag alpine:latest my-registry.my-company.io/alpine:latest
me@vm:~$ docker push my-registry.my-company.io/alpine:latest
The push refers to a repository [my-registry.my-company.io/alpine]
77cae8ab23bf: Pushed
latest: digest: sha256:e4355b66995c96b4b468159fc5c7e3540fcef961189ca13fee877798649f531a size: 528

Во-вторых,ваш анализ может быть выполнен внутри контейнера в цикле, а не в отдельном шаге:

stage('Pull and Push Image') {
    agent {
        label "kaniko"
    }
    steps {
        container(name: 'kaniko', shell: '/busybox/sh') {
            withCredentials([
                string(credentialsId: 'infra', variable: 'PASS')
            ]) {
                withEnv(['PATH+EXTRA=/busybox:/kaniko']) {
                    // RUN THE LOOP HERE
                    script {
                    params.IMAGES.split("\\r?\\n").each{ oldfullPath ->
                        def (path, tag) = oldfullPath.tokenize( ':' )
                        def app = path.tokenize('/')[-1]
                        println "App is ${app} and Tag is ${tag}"
                        switch(params.REPO) {
                            case "monitoring":
                                image = "eu.gcr.io/<PROJECT>/infra/monitoring"
                                break
                            case "apps":
                                image = "eu.gcr.io/<PROJECT>/infra/apps"
                                break
                        }
                        def newFullPath = "${image}/${app}:${tag}"
                        println "Full old image path is ${oldfullPath}"
                        println "Full new image path is ${newFullPath}"

                    sh """#!/busybox/sh
                    echo "FROM ${oldfullPath}" | \
                    /kaniko/executor \
                        --dockerfile /dev/stdin \
                        --destination ${newFullPath}
                    """
              // adjust closing brackets as needed 

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

Теперь давайте предположим, что ваш реальный вопрос: «Как запустить еще неизвестное число параллельных этапов в декларативном конвейере?»

Ответ на этот вопросесть, вы можете программно построить свой конвейер, как это:

images_array = ["quay.io/one", "docker.io/two", "docker.io/three"] // or split params as needed

def getBuilders()
{
    def builders = [:]

    images_array.eachWithIndex { it, index ->
        // name the stage
        def name = 'Build image #' + (index + 1)
        builders[name] = {
            stage (name) {
                def my_label = "kaniko" // can choose programmatically if needed
                node(my_label) {
                    timeout(time: 2, unit: 'HOURS') { 
                        try {
                            buildOneImage(it)
                        }
                        catch (err) { println "Failed to build ${it}"; throw err  }
                        finally {  }
                    }
                }
            }
        }
    };
    return builders
}

def buildOneImage(old_path) {
   // replace path as needed, build image
   // use scripted-style pipeline, not the declarative one
}

И позже в вашем основном конвейере

        stage('Build all images') {
            steps {
                script {
                    def builders = getBuilders()
                    parallel builders
                }
            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...