8
$ groovy --version
Groovy Version: 2.4.15 JVM: 1.8.0_171 Vendor: Oracle Corporation OS: Mac OS X

I want execute some AWS CLI commands in Groovy, eventually in a Jenkinsfile to run in Jenkins of course.

But for prototyping, I want to code it on my Mac and execute it as a plain Groovy script. So I have this, for example.

#!/usr/bin/env groovy

def getEBSVolumes(awsRegion) {
  def regions
  if (awsRegion == "all") {
    regions = sh(returnStdout: true, script: """#!/usr/bin/env bash
                   aws ec2 describe-regions --output text|awk '{print \$3}'
                 """
                )
  }
  else {
    regions = awsRegion
  }
  echo "Regions: regions"
}

getEBSVolumes("all")

When I execute it, I get

$ ./x.groovy 
Caught: groovy.lang.MissingMethodException: No signature of method: x.sh() is applicable for argument types: (java.util.LinkedHashMap) values: [[returnStdout:true, script:#!/usr/bin/env bash
                   aws ec2 describe-regions --output text|awk '{print $3}'
                 ]]
Possible solutions: use([Ljava.lang.Object;), is(java.lang.Object), run(), run(), any(), each(groovy.lang.Closure)
groovy.lang.MissingMethodException: No signature of method: x.sh() is applicable for argument types: (java.util.LinkedHashMap) values: [[returnStdout:true, script:#!/usr/bin/env bash
                   aws ec2 describe-regions --output text|awk '{print $3}'
                 ]]
Possible solutions: use([Ljava.lang.Object;), is(java.lang.Object), run(), run(), any(), each(groovy.lang.Closure)
    at x.getEBSVolumes(x.groovy:9)
    at x$getEBSVolumes.callCurrent(Unknown Source)
    at x.run(x.groovy:20)

Can someone please explain the cryptic error message? Thanks!

Note the code works when executed in a Jenkinsfile, hence I specifically asked about CLI Groovy.

daspilker
  • 8,154
  • 1
  • 35
  • 49
Chris F
  • 14,337
  • 30
  • 94
  • 192

2 Answers2

12

You wont be able to run this script locally with Groovy only, because it fails due to missing sh method in your script. This sh method is a step provided by Jenkins Pipeline DSL library - https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#code-sh-code-shell-script

I would suggest you running your local Jenkins - the easiest way to do it is to use an existing Docker image. I use for example following docker-compose.yml file:

jenkins:
  image: jenkins:2.60.3-alpine
  container_name: jenkins
  ports:
    - 8080:8080
  volumes:
    - ./home:/var/jenkins_home

and whenever I want to run my local Jenkins I just go the directory where I have this file stored, e.g.

cd ~/workspace/jenkins

and I simply call

docker-compose up -d

which boots Jenkins I can access via http://localhost:8080 In this local instance I am able to test pipeline scripts inside Groovy Sandbox or by setting up a scripted pipeline.

Alternative: JenkinsPipelineUnit testing library

If you want to unit test your pipeline scripts you can use JenkinsPipelineUnit library which allows you to unit test the flow of your pipeline. However in this case you would have to register your own sh method, because the BasePipelineTest class mocks it with NOOP:

helper.registerAllowedMethod("sh", [Map.class], null)

It means that each interaction with sh step gets counted but it does not trigger the script defined with script: '' property.

I would say that setting up your own local Jenkins sandbox where you can play around with Jenkinsfile scripts is the easiest way to start with.

Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
  • Thanks, I'll setup my Jenkins sandbox indeed. – Chris F Jun 06 '18 at 14:05
  • When go to localhost:8080, it tells me to get the secret from /var/jenkins_home, but that folder is not there since root owns /var and it's 0755. So I restart the whole process and set ./home in the yml file to /Users/myuser/jenkins_home, and see NO files there either? Even then, the message in localhost:8080 still tells me to got the /var/jenkins_home? – Chris F Jun 06 '18 at 15:04
  • In my case container's `/var/jenkins_home` is mounted to `~/workspace/jenkins/home` (docker-compose file is located in `~/workspace/jenkins` folder). I don't remember if I had to create this `home` directory manually or if I had to change permissions to this folder while it got created, but I would try creating it and setting permissions if needed. – Szymon Stepniak Jun 06 '18 at 15:11
  • Got it to work, thanks! I followed you suggestion exactly. – Chris F Jun 06 '18 at 15:20
  • New to docker. How do I add AWS CLI in the docker-compose.yml file? Or any package for that matter? – Chris F Jun 06 '18 at 16:12
  • 1
    The simplest way might be to use an image that provides AWS CLI directly, e.g. https://hub.docker.com/r/dalekurt/jenkins-awscli/ this one – Szymon Stepniak Jun 06 '18 at 16:18
  • Thanks. So in your yml example, instead of using jenkins:2.60.3-alpine I use dalekurt/jenkins-awscli for the image? – Chris F Jun 06 '18 at 16:30
  • `jenkins:2.60.3-alpine` image is deprecated. I think `jenkins/jenkins:latest` would be the replacement – pupher Sep 09 '21 at 21:27
  • Don't forget to install the correct plugins – pupher Sep 09 '21 at 21:49
  • it asks for plugins! – gdm May 25 '23 at 14:22
0

Adding onto the answer by @Szymon-Stepniak -- once you have a jenkins instance running

  • New item
  • Type: pipeline (may be dependent on Pipeline: Job / Pipeline: Groovy plugins)
  • configure pipeline script
storm_m2138
  • 2,281
  • 2
  • 20
  • 18