问题描述
我有一个Groovy库可作为全局共享库使用:
I have a Groovy library made available as a Global shared library:
package com.example
@Grab(group="org.apache.httpcomponents", module="httpclient", version="[4.5.3,)")
import org.apache.http.HttpHost
import org.apache.http.impl.client.HttpClients
class MyClass implements Serializable {
static def run() {
return HttpClients.custom()
.setProxy(new HttpHost("proxy.example.com", 3128))
.build()
}
static def debug() {
return ("""
this: ${this.classLoader.class.toString()} ${this.classLoader.hashCode().toString()}
HttpHost: ${HttpHost.class.classLoader.class.toString()} ${HttpHost.class.classLoader.hashCode()}
HttpClients: ${HttpClients.class.classLoader.class.toString()} ${HttpClients.class.classLoader.hashCode()}
""")
}
}
这个库:
@Library('example') _
node {
echo "${com.example.MyClass.debug()}"
com.example.MyClass.run()
}
当作业运行时,我从 debug()
得到以下输出,然后从 run()
:
When the job is run, I get the following output from debug()
, followed by an error from run()
:
this: class org.jenkinsci.plugins.workflow.cps.CpsGroovyShell$CleanGroovyClassLoader 765101363
HttpHost: class hudson.ClassicPluginStrategy$AntClassLoader2 804623541
HttpClients: class hudson.ClassicPluginStrategy$AntClassLoader2 1870591909
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.apache.http.impl.client.HttpClientBuilder.setProxy() is applicable for argument types: (org.apache.http.HttpHost) values: [http://proxy.example.com:3128]
Possible solutions: setProxy(org.apache.http.HttpHost)
The following classes appear as argument class and as parameter class, but are defined by different class loader
很明显,一些Jenkins插件已经依赖于httpcomponents,以下看起来是正确的:
It is clear to me that some Jenkins plugin already has a dependency on httpcomponents, and the following seem true:
- 我的
@Grab
注释导致请求的httpclient版本(在〜/ .groovy / grapes
中观察到)。 - 但是,该版本未被加载或使用Groovy库,但一些其他版本是一些Jenkins插件的依赖。
- 更令人讨厌的是,
HttpHost
和HttpClients
是从不同的类加载器加载的,因此我甚至无法使用泄露到我的Groovy代码的类加载器中的插件版本。
- My
@Grab
annotation caused the requested version of httpclient to be downloaded (as observed in~/.groovy/grapes
). - But, that version is not being loaded or used by the Groovy library, but some other version that is a dependency of some Jenkins plugin.
- And, even more annoyingly,
HttpHost
andHttpClients
are being loaded from different classloaders such that I cannot even use the plugin's version that leaked into my Groovy code's classloader.
版本
- Jenkins:2.20
Versions
- Jenkins: 2.20
- Groovy:2.0
- / li>
- 管道:Groovy:2.30
- 管道:Sha red Groovy库:2.8
有没有办法在类似于Jenkins插件的类加载器中运行我的Groovy? Jenkins和Groovy共享库代码如何组织类加载器?这是否是由有意插件引发的类泄漏?
Is there a way to run my Groovy in a classloader that is isolated from that of Jenkins plugins? How do Jenkins and the Groovy shared library code organize the classloaders? Is this leaking of classes pulled in by plugins intentional?
这是一个错误还是我做错了什么?我知道我在Jenkins上有几个版本,所以这是一个尝试。
Is this a bug or am I doing something wrong? I realize I am several versions behind on Jenkins, so that's one thing to try.
因为系统是无法使用的,除非我有幸拥有依赖关系其他插件已经或者很幸运地与类加载器发现的任何版本兼容。
As is, the system is unusable unless I'm lucky enough to have dependencies that no other plugin has, or lucky to be compatible with whatever version the classloader happens to find.
推荐答案
@当库被限制到文件夹时,Grab
不起作用。在库中使用@Grab
只能在全局设置中配置库时使用。根据插件结构文档。@Grab
does not work when libraries are scoped to folders. Using@Grab
in a library only works when the library is configured in the global settings. This is intentional and not a bug with Jenkins according to the plugin structure documentation.文件继续说:
The documentation goes on to say:
个人而言,我会在尝试上述步骤之前将Jenkins(和Pipelines)升级到最新版本。
Personally, I would upgrade Jenkins (and Pipelines) to the latest version available before trying the above.
这篇关于我怎样才能隔离我的Jenkins管道Groovy共享库类加载器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!