当前位置: 首页 > 知识库问答 >
问题:

如何隔离Jenkins管道Groovy共享库类加载器?

屠德宇
2023-03-14

我有一个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()}
    """)
  }
}

以及使用此库的Jenkins脚本化管道作业:

@Library('example') _
node {
  echo "${com.example.MyClass.debug()}"
  com.example.MyClass.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

我很清楚,一些Jenkins插件已经依赖于httpcomponents,以下情况似乎是正确的:

  1. 我的@Grab注释导致所请求的http客户端版本被下载(如~/. groovy/grapes中观察到的)。
  2. 但是,Groovy库没有加载或使用该版本,而是依赖于Jenkins插件的其他版本。
  3. 而且,更恼人的是,HttpHostHttpClients是从不同的类加载器加载的,这样我甚至不能使用泄漏到Groovy代码的类加载器中的插件版本。
  • 詹金斯:2.20
  • Groovy: 2.0
  • 管道:2.5
  • 管道: Groovy: 2.30
  • 管道:共享Groovy库:2.8

有没有办法在一个与Jenkins插件隔离的类加载器中运行我的Groovy?Jenkins和Groovy共享库代码如何组织类加载器?这个外挂拉进来的类泄露是故意的吗?

这是窃听器还是我做错了什么?我意识到我落后詹金斯几个版本,所以这是值得尝试的一件事。

就目前而言,除非我有幸拥有其他插件所没有的依赖项,或者幸运地与类加载器碰巧找到的任何版本兼容,否则该系统是不可用的。

共有1个答案

蔺宇
2023-03-14

@Grab在库作用域为文件夹时不起作用。在库中使用@Grab只有在库在全局设置中配置时才有效。这是故意的,而不是根据插件结构留档与Jenkins的错误。

文件接着说:

如果您希望在这些库之前加载您自己的库(例如,您想要更新版本的velocity或其他库),您可以通过在pom中告知hpi插件,将插件配置为使用不同的类加载器策略。xml

就我个人而言,在尝试上述版本之前,我会将Jenkins(和管道)升级到可用的最新版本。

 类似资料:
  • 问题内容: 詹金斯版 2.89.4workflow -cps ver 2.42 当我尝试运行加载库的管道时,出现以下异常: 引用链接的Groovy类: 您可以像这样在管道或库中重现异常: 问题答案: 这是一个已知的詹金斯问题:JENKINS-45901 自2017年8月以来已开放。看起来很快不会修复: 不知道是否有详尽的文档记录了Groovy语言支持(或缺乏它),但是无论如何我都不会期望这个问题或

  • 詹金斯·弗。2.89.4 workflow-cps ver 2.42 当我尝试运行一个加载库的管道时,我得到以下异常: 链接所引用的Groovy类: 您可以在管道或库中复制异常,如下所示:

  • 我目前正在尝试从jenkins管道中的文件加载一个自定义groovy类。我尝试了这里提出的解决方案: 如何在Jenkins管道中导入类文件? 作为... JenkinsPipelineUtilityClass.groovy 詹金斯档案 并尝试同样使用GroovyClassLoader(再次使用上述类) 詹金斯档案 我在这两方面都遇到了同样的错误: 我已经检查了正在进行的脚本批准,里面什么都没有,我

  • 我们试图切换到jenkins管道,但我在groovy/java的低水平阻止了我们建立一个共享库。 这里是我的共享库(位于bitbucket中git repo的{root}/src/com/pipeline.groovy中)我必须承认,我在这里做什么都不知道,因为我不知道包裹的定义 Jenkins的管道看起来 通过所有这些设置,我最终得到了错误: 我怀疑我的漂亮包裹的定义,但我坚持这样做。 非常欢迎

  • 我将我的Jenkins Pipeline存储为Jenkins共享库中的Groovy脚本。我想为不同的工作使用不同的版本。我的共享库脚本称为如下: 我已将sharedLib repo中的不同版本标记为。万一我想用v1。0,我用注释引用了它,如下所示。 在我的工作中,我通过调用groovy脚本访问了共享库,并使用了上面的注释,如图所示: 我运行这项工作时出错了。以下是我看到的错误。 当我使用。我哪里出

  • 我的詹金斯大师没有遗嘱执行人,因为我们公司有詹金斯的设计,所以不可能有遗嘱执行人。我们有两个工作节点。当我添加管道共享库时,默认情况下Jenkins尝试在master中签出,但由于明显的原因失败,因为它找不到git,因为它在Jenkins master中不可用。 我不明白为什么詹金斯甚至可以尝试在大师中检出共享库,因为大师甚至没有遗嘱执行人。 我看了别人的意见,但我的东西停在它试图检查的地方。我怎