简体   繁体   English

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

[英]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,以下似乎是正确的:

  1. My @Grab annotation caused the requested version of httpclient to be downloaded (as observed in ~/.groovy/grapes ). 我的@Grab注释导致了httpclient的请求版本被下载(在~/.groovy/grapes观察到)。
  2. 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. 但是,Groovy库没有加载或使用该版本,但是某些其他版本是某些Jenkins插件的依赖项。
  3. And, even more annoyingly, 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. 而且,更令人讨厌的是, HttpHostHttpClients正在从不同的类加载器加载,因此我甚至无法使用泄漏到我的Groovy代码的类加载器中的插件版本。

Versions 版本

  • Jenkins: 2.20 詹金斯:2.20

Plugins Versions 插件版本

  • Groovy: 2.0 Groovy:2.0
  • Pipeline: 2.5 管道:2.5
  • Pipeline: Groovy: 2.30 管道:Groovy:2.30
  • Pipeline: Shared Groovy Libraries: 2.8 管道:共享Groovy库:2.8

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.

相关问题 如何在继承自管道共享库的声明性 jenkins 管道中定义其他参数? - How can I define additional parameters in a declarative jenkins pipeline who inherit from a pipeline shared library? 管道共享库jenkins不支持Groovy @Delegate类注释 - Groovy @Delegate class annotations are not supported in the pipeline shared library jenkins 在 jenkins 管道中重用 groovy 对象/类 - 共享库 - Reuse groovy object / class in jenkins pipeline - shared library 使用管道和常规,如何从Jenkins中提取我当前构建的测试结果? - Using pipeline & groovy, How can I extract test results from Jenkins for my current build? Jenkins 管道共享库 - Jenkins pipeline shared library 如何在 Jenkins 文件(管道)中使用共享库中的 groovy 常量? - How to use groovy constant from Shared Libray in Jenkins file (pipeline)? Jenkins共享库中的Groovy作用域 - Groovy scoping in Jenkins Shared Library 我可以为脚本式管道到声明式方法中的方法创建共享库.groovy脚本吗 - Can i create a shared library .groovy script for a method in scripted pipeline into declarative 如何在Jenkins声明性管道中导入的groovy脚本中使用@Library? - How to use @Library in an imported groovy script in Jenkins declarative pipeline? 我可以在 Jenkins 管道中通过普通 Groovy 方法运行并行操作吗? - Can I run parallel actions from a plain Groovy method in my Jenkins pipeline?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM