2

I get a NonSerializableException when i put my test() call inside a script, when I commented out line A and uncommented out line B, it works just fine.

What's the difference from calling test() inside a script and outside of it?

The workaround I'm considering for now is to use the when conditions for Jenkinsfile

UPDATE I suspect that the error is related to Commands Requiring a “node” Block

Jenkinsfile

#!/usr/bin/env groovy
import groovy.json.JsonSlurper

@NonCPS
def test() {
    sh "aws ecs update-service --cluster dev-cluster-name --service service-name --desired-count 0 --region us-west-2"
}

def deployDockerContainer() {
    script {
        def describeServices = sh(returnStdout: true, script: "aws ecs describe-services --region us-west-2 --cluster dev-cluster-name --services service-name").trim()
        def describeServicesJSON = new JsonSlurper().parseText(describeServices)

        if (describeServicesJSON.services.size() > 0 && describeServicesJSON.services[0].status.equals('ACTIVE')) {
            test() //A
        }
    }
    // test() //B
    sh "/usr/local/bin/ecs-cli ps --region us-west-2a --cluster dev-clustername"
}

pipeline {
    agent any

    environment {
        ENVIRONMENT = 'dev'
    }

    parameters {
        booleanParam(name: 'DEPLOY_TO_DEV', defaultValue: true, description: 'Deploy to Dev Environment?')
        booleanParam(name: 'DEPLOY_TO_TEST', defaultValue: false, description: 'Deploy to Test Environment?')
        booleanParam(name: 'DEPLOY_TO_PROD', defaultValue: false, description: 'Deploy to Production Environment?')
    }

    stages {
        stage('DEV:Deploy') {
            when {
                expression {
                    return params.DEPLOY_TO_DEV
                }
            }
            environment {
                ENVIRONMENT = 'dev'
            }
            steps {
                deployDockerContainer()
            }
        }
    }
}

Stacktrace:

an exception which occurred:
    in field com.cloudbees.groovy.cps.impl.BlockScopeEnv.locals
    in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@4c090b96
    in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
    in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@45444499
    in field com.cloudbees.groovy.cps.impl.CallEnv.caller
    in object com.cloudbees.groovy.cps.impl.FunctionCallEnv@2e3aa6ff
    in field com.cloudbees.groovy.cps.Continuable.e
    in object org.jenkinsci.plugins.workflow.cps.SandboxContinuable@8393d12
    in field org.jenkinsci.plugins.workflow.cps.CpsThread.program
    in object org.jenkinsci.plugins.workflow.cps.CpsThread@46045514
    in field org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.threads
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@420ee007
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@420ee007
Caused: java.io.NotSerializableException: groovy.json.internal.LazyMap
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at java.util.HashMap.internalWriteEntries(HashMap.java:1790)
    at java.util.HashMap.writeObject(HashMap.java:1363)
    at sun.reflect.GeneratedMethodAccessor322.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:273)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at java.util.TreeMap.writeObject(TreeMap.java:2438)
    at sun.reflect.GeneratedMethodAccessor336.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:273)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
    at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.lambda$writeObject$0(RiverWriter.java:144)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
    at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.writeObject(RiverWriter.java:143)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:477)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:453)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgramIfPossible(CpsThreadGroup.java:440)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:367)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
    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)

Executing aws ecs update-service manually:

{
    "service": {
        "serviceArn": "XXXXXXXX",
        "serviceName": "XXXXXXXX",
        "clusterArn": "XXXXXXXX",
        "loadBalancers": [
            {
                "targetGroupArn": "XXXXXXXX",
                "containerName": "XXXXXXXX",
                "containerPort": 8080
            }
        ],
        "serviceRegistries": [],
        "status": "ACTIVE",
        "desiredCount": 0,
        "runningCount": 0,
        "pendingCount": 0,
        "launchType": "EC2",
        "taskDefinition": "XXXXXXXX",
        "deploymentConfiguration": {
            "maximumPercent": 200,
            "minimumHealthyPercent": 100
        },
        "deployments": [
            {
                "id": "XXXXXXXX",
                "status": "PRIMARY",
                "taskDefinition": "XXXXXXXX",
                "desiredCount": 0,
                "pendingCount": 0,
                "runningCount": 0,
                "createdAt": 1525230109.446,
                "updatedAt": 1525234874.41,
                "launchType": "EC2"
            }
        ],
        "roleArn": "XXXXXXXX",
        "events": [
            {
                "id": "XXXXXXXX",
                "createdAt": 1525230133.646,
                "message": "XXXXXXXX has reached a steady state."
            },
            {
                "id": "XXXXXXXX",
                "createdAt": 1525230121.278,
                "message": "XXXXXXXX has stopped 1 running tasks: (task XXXXXXXX)."
            },
            {
                "id": "XXXXXXXX",
                "createdAt": 1525230109.914,
                "message": "(service XXXXXXXX) has started 1 tasks: (task XXXXXXXX)."
            }
        ],
        "createdAt": 1525230109.446,
        "placementConstraints": [],
        "placementStrategy": [],
        "healthCheckGracePeriodSeconds": 0
    }
}
letthefireflieslive
  • 11,493
  • 11
  • 37
  • 61
  • 1
    First, don't use any steps inside of a `@NonCPS` block (see [here](https://jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice/)). For your issue, you are running into something similar to https://stackoverflow.com/questions/37864542/jenkins-pipeline-notserializableexception-groovy-json-internal-lazymap – mkobit May 02 '18 at 12:44

1 Answers1

4

First of all JsonSlurperis not serializable. If you want to use it you have to encapsulate it into a @NonCPS method.

Second you cannot use any cps methods from within a @NonCPS method, like sh.

Third, sometimes the pipeline (cps code) runner does not immediately throw an error if you do not follow those rules. Sometimes the error is thrown after doing some changes to the script which itself are correct.

Joerg S
  • 4,730
  • 3
  • 24
  • 43