【问题标题】:groovy.lang.MissingMethodException: No signature of method: sh() is applicable for argument types while testing AWS CLI commands in Groovygroovy.lang.MissingMethodException:没有方法签名:sh() 在 Groovy 中测试 AWS CLI 命令时适用于参数类型
【发布时间】:2018-06-06 13:40:45
【问题描述】:
$ groovy --version
Groovy Version: 2.4.15 JVM: 1.8.0_171 Vendor: Oracle Corporation OS: Mac OS X

我想在 Groovy 中执行一些 AWS CLI 命令,当然最终在 Jenkinsfile 中运行。

但对于原型设计,我想在我的 Mac 上对其进行编码,并将其作为一个普通的 Groovy 脚本执行。例如,我有这个。

#!/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")

当我执行它时,我得到

$ ./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)

有人可以解释一下神秘的错误信息吗?谢谢!

注意代码在 Jenkinsfile 中执行时有效,因此我专门询问了 CLI Groovy。

【问题讨论】:

    标签: groovy jenkins-pipeline


    【解决方案1】:

    您将无法仅使用 Groovy 在本地运行此脚本,因为脚本中缺少 sh 方法导致它失败。这个sh 方法是Jenkins Pipeline DSL 库提供的一个步骤-https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#code-sh-code-shell-script

    我建议您运行本地 Jenkins - 最简单的方法是使用现有的 Docker 映像。例如,我使用以下docker-compose.yml 文件:

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

    每当我想运行我的本地 Jenkins 时,我只需转到存储此文件的目录,例如

    cd ~/workspace/jenkins
    

    我只是打电话

    docker-compose up -d
    

    我可以通过http://localhost:8080 访问哪个启动 Jenkins 在这个本地实例中,我可以在 Groovy Sandbox 中测试管道脚本或通过设置脚本管道。

    替代方案:JenkinsPipelineUnit 测试库

    如果您想对管道脚本进行单元测试,您可以使用JenkinsPipelineUnit 库,它允许您对管道的流程进行单元测试。但是在这种情况下,您必须注册自己的 sh 方法,因为 BasePipelineTest 类使用 NOOP 模拟它:

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

    这意味着与sh 步骤的每次交互都会被计算在内,但不会触发使用script: '' 属性定义的脚本。

    我会说,设置您自己的本地 Jenkins 沙箱,您可以在其中使用 Jenkinsfile 脚本是最简单的开始方式。

    【讨论】:

    • 谢谢,我确实会设置我的 Jenkins 沙箱。
    • 当转到 localhost:8080 时,它告诉我从 /var/jenkins_home 获取秘密,但该文件夹不存在,因为 root 拥有 /var 并且它是 0755。所以我重新启动整个过程并将 yml 文件中的 ./home 设置为 /Users/myuser/jenkins_home,并且在那里也看到 NO 文件?即使这样,localhost:8080 中的消息仍然告诉我获取 /var/jenkins_home?
    • 在我的情况下,容器的 /var/jenkins_home 已安装到 ~/workspace/jenkins/home(docker-compose 文件位于 ~/workspace/jenkins 文件夹中)。我不记得是否必须手动创建此 home 目录,或者是否必须在创建此文件夹时更改对它的权限,但如果需要,我会尝试创建它并设置权限。
    • 得到它的工作,谢谢!我完全听从了你的建议。
    • 最简单的方法可能是使用直接提供 AWS CLI 的图像,例如hub.docker.com/r/dalekurt/jenkins-awscli这个
    【解决方案2】:

    添加到@Szymon-Stepniak 的答案——一旦你运行了一个詹金斯实例

    • 新项目
    • 类型:管道(可能依赖于管道:作业/管道:Groovy 插件)
    • 配置管道脚本

    【讨论】:

      猜你喜欢
      • 2017-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      • 2017-04-08
      • 2018-12-19
      • 1970-01-01
      • 2021-11-02
      相关资源
      最近更新 更多