3

I am trying to choose a different docker agent from a private container registry based on an a parameter in Jenkins pipeline. For my example let's say I have 'credsProd' and 'credsTest' saved in the credentials store. My attempt is as follows:

pipeline {
    parameters {
        choice(
            name: 'registrySelection', 
            choices: ['TEST', 'PROD'],
            description: 'Is this a deployment to STAGING or PRODUCTION environment?'
        )
    }
    environment {
        URL_VAR = "${env.registrySelection == "PROD" ? "urlProd.azure.io" : "urlTest.azure.io"}"
        CREDS_VAR = "${env.registrySelection == "PROD" ? "credsProd" : "credsTest"}"
    }
    agent {
        docker {
            image "${env.URL_VAR}/image:tag"
            registryUrl "https://${env.URL_VAR}"
            registryCredentialsId "${env.CREDS_VAR}"
        }
    }
  stages{
      stage('test'){
          steps{
            echo "${env.URL_VAR}"
            echo "${env.CREDS_VAR}"
          }
      }
  }
}

I get error: Error response from daemon: Get https://null/v2/: dial tcp: lookup null on

If I hard code the registryUrl I get a similar issue with registryCredentialsId:

agent {
    docker {
        image "${env.URL_VAR}/image:tag"
        registryUrl "https://urlTest.azure.io"
        registryCredentialsId "${env.CREDS_VAR}"
    }
}

ERROR: Could not find credentials matching null

It is successful if I hardcode both registryUrl and registryCredentialsId.

agent {
    docker {
        image "${env.URL_VAR}/image:tag"
        registryUrl "https://urlTest.azure.io"
        registryCredentialsId "credsTest"
    }
}

It appears that the docker login stage of the agent{docker{}} cannot access/resolve environment variables.

Is there a way around this that does not involve code duplication? I manage changes with multi branch pipeline so ideally do not want to have separate Prod and test groovy files or different sets sequential steps in the same file.

DataJack
  • 341
  • 2
  • 13
  • I believe the `env` map is always `null` in the `agent` block (indeed google yields https://issues.jenkins-ci.org/browse/JENKINS-43911). I believe the `params` map is likewise, but I thought I saw an example in a doc somewhere that implied it might work. Also check this out: https://stackoverflow.com/questions/46630168/in-a-declarative-jenkins-pipeline-can-i-set-the-agent-label-dynamically – Matthew Schuchard Mar 20 '19 at 18:09
  • Thanks @MattSchuchard that Jenkins issue was a helpful read. Clearly trying to do something not possible here. – DataJack Mar 21 '19 at 09:31

1 Answers1

2

Try running a scripted pipeline before declarative:

URL_VAR = null
CREDS_VAR = null

node('master') {
    stage('Choose') {
        URL_VAR = params.registrySelection == "PROD" ? "urlProd.azure.io" : "urlTest.azure.io"
        CREDS_VAR = params.registrySelection == "PROD" ? "credsProd" : "credsTest"
    }
}


pipeline {
    agent {
        docker {
            image "${URL_VAR}/image:tag"
            registryUrl "https://${URL_VAR}"
            registryCredentialsId "${CREDS_VAR}"
        }
    }
...

Alternatively, you can define two stages (with hard-coded url and creds) but run only one of them, using when in both.

MaratC
  • 6,418
  • 2
  • 20
  • 27