4

Our pipeline by default tries to use a container that matches the name of the current stage. If this container doesn't exist, the container 'default' is used. This functionality works but the problem is that when the container that matches the name of the stage doesn't exist, a ProtocolException occurs, which isn't catchable because it is thrown by a thread that is out of our control. Is there a way to check if a container actually exists when using the Kubernetes plugin for Jenkins to prevent this exception from appearing? It seems like a basic function but I haven't been able to find anything like this online.

I can't show the actual code but here's a pipeline-script example extract that would trigger this exception:

node(POD_LABEL)
        stage('Check Version (Maven)') {
            container('containerThatDoesNotExist'}{
                try{
                    sh 'mvn --version'
                }catch(Exception e){
                    // catch Exception
                }
        }
java.net.ProtocolException: Expected HTTP 101 response but was '400 Bad Request'
    at okhttp3.internal.ws.RealWebSocket.checkResponse(RealWebSocket.java:229)
    at okhttp3.internal.ws.RealWebSocket$2.onResponse(RealWebSocket.java:196)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:203)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
    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)
RedEclipse
  • 41
  • 1
  • 3

1 Answers1

1

You can run a pre stage in order to get the current running container by exec kubectl command to server. The tricky point is that kubectl does not exist on worker - so in that case:

  1. pull an image of kubectl on worker.
  2. Add a stage for getting the running container - use a label or timestamp to get the desire one.
  3. Use the right container 'default' or rather 'some-container'.

Example:

pipeline {
    
    environment {
    CURRENT_CONTAINER="default"
  }

  agent {
    kubernetes {
      defaultContainer 'jnlp'
      yaml '''
        apiVersion: v1
        kind: Pod
        spec:
          containers:
          - name: some-app
            image: XXX/some-app
            imagePullPolicy: IfNotPresent
            tty: true
          - name: kubectl
            image: gcr.io/cloud-builders/kubectl
            imagePullPolicy: IfNotPresent
            command:
            - cat
            tty: true
        '''
    }
  }
  stages {
    stage('Set Container Name') {
      steps {
          container('kubectl') {
            withCredentials([
            string(credentialsId: 'minikube', variable: 'api_token')
            ]) {
            script {
                    CURRENT_CONTAINER=sh(script: 'kubectl get pods -n jenkins -l job-name=pi -o jsonpath="{.items[*].spec.containers[0].name}"',
                                        returnStdout: true
                                        ).trim()
                    echo "Exec container ${CURRENT_CONTAINER}"
            }
          }
        }
      }
    }
    
    stage('Echo Container Name') {
      steps {
          echo "CURRENT_CONTAINER is ${CURRENT_CONTAINER}"
      }
    }
  }
}