[英]How can I isolate my Jenkins pipeline Groovy shared library classloader?
I have a Groovy library made available as a Global shared library: 我有一个Groovy库作为全局共享库提供:
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()}
""")
}
}
And a Jenkins scripted pipeline job using this library: 以及使用此库的Jenkins脚本管道作业:
@Library('example') _
node {
echo "${com.example.MyClass.debug()}"
com.example.MyClass.run()
}
When the job is run, I get the following output from debug()
, followed by an error from run()
: 当作业运行时,我从
debug()
获得以下输出,然后是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
It is clear to me that some Jenkins plugin already has a dependency on httpcomponents, and the following seem true: 我很清楚,一些Jenkins插件已经依赖于httpcomponents,以下似乎是正确的:
@Grab
annotation caused the requested version of httpclient to be downloaded (as observed in ~/.groovy/grapes
). @Grab
注释导致了httpclient的请求版本被下载(在~/.groovy/grapes
观察到)。 HttpHost
and HttpClients
are being loaded from different classloaders such that I cannot even use the plugin's version that leaked into my Groovy code's classloader. HttpHost
和HttpClients
正在从不同的类加载器加载,因此我甚至无法使用泄漏到我的Groovy代码的类加载器中的插件版本。 Is there a way to run my Groovy in a classloader that is isolated from that of Jenkins plugins? 有没有办法在与Jenkins插件隔离的类加载器中运行我的Groovy? How do Jenkins and the Groovy shared library code organize the classloaders?
Jenkins和Groovy如何共享库代码来组织类加载器? Is this leaking of classes pulled in by plugins intentional?
这种类型的泄漏是否是故意插入的?
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
does not work when libraries are scoped to folders. 当库限定为文件夹时,
@Grab
不起作用。 Using @Grab
in a library only works when the library is configured in the global settings. 只有在全局设置中配置库时,
@Grab
在库中使用@Grab
。 This is intentional and not a bug with Jenkins according to the plugin structure documentation . 根据插件结构文档,这是故意的,而不是Jenkins的错误。
The documentation goes on to say: 文档继续说:
If you want to have your own libaries loaded before these (eg you want a newer version of velocity or an other library), you can configure your plugin to use a different classloader strategy by telling the hpi plugin in your pom.xml
如果您希望在这些库之前加载自己的库(例如,您需要更新版本的velocity或其他库),可以通过告诉pom.xml中的hpi插件将插件配置为使用不同的类加载器策略
Personally, I would upgrade Jenkins (and Pipelines) to the latest version available before trying the above. 就个人而言,在尝试上述操作之前,我会将Jenkins(和Pipelines)升级到最新版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.