这是我正在使用的 Jenkins 声明式管道的简化:
pipeline {
agent any
stages {
stage("demo") {
steps {
script {
def co_url = 'https://bitbucket.company.com/scm/demo/prj.git'
checkout( [$class: 'GitSCM',
branches: [[name: 'my_branch']],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'RelativeTargetDirectory',
relativeTargetDir: 'prj']],
submoduleCfg: [],
userRemoteConfigs: [[url: co_url]]] )
dir(WORKSPACE + "/prj") {
def img = docker.build("foo:1.0.0", "--target fubar .")
def container = img.withRun()
}
}
}
}
}
}
为什么
def container = img.withRun()
行会生成此错误:
Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object (org.jenkinsci.plugins.docker.workflow.Docker$Image withRun). Administrators can decide whether to approve or reject this signature.
...而
def container = img.run()
则不然?
withRun()
本来会更受欢迎,因为它的界面比保证清理更干净,但对我来说,管理上允许选定的脚本不是一个选项。
这是一个老问题,但这是你的答案:
docker.withRun()
需要向其传递一个块参数;例如,这是从 jenkins 文档中提取的内容:
node {
checkout scm
/*
* In order to communicate with the MySQL server, this Pipeline explicitly
* maps the port (`3306`) to a known port on the host machine.
*/
docker.image('mysql:8-oracle').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"' +
' -p 3306:3306') { c ->
/* Wait until mysql service is up */
sh 'while ! mysqladmin ping -h0.0.0.0 --silent; do sleep 1; done'
/* Run some tests which require MySQL */
sh 'make check'
}
}
在您的示例中,您没有向其传递一个块以在容器内执行操作。您必须传递该块参数;没有它,Jenkins 中的常规实现将无法找到该方法。
现在您可能会问,为什么没有收到类似“没有这样的方法”或“错误的参数类型”或模糊相关的内容的错误消息?
因为 Jenkins 开发人员已经决定,拼写错误的方法名称或(如此处)不正确的参数会生成这个晦涩的安全错误,或者至少这是一个小问题,不值得修复 Jenkins 脚本沙箱之间的交互以及 Groovy 进行方法解析的标准方式。
至少从 2016 年起,Jenkins 就是这样,除了一些 stackoverflow 答案之外,我能找到的任何地方都没有记录;您只需要知道,当您遇到有关
groovy.lang.GroovyObject invokeMethod
不允许的安全错误时,通常意味着您拼错了方法名称或传递了错误类型的参数。