如何在本地Groovy脚本中创建Jenkins实例并兼容WorkflowJob类?
我想在本地Groovy脚本里调用Jenkins API,替代Jenkins的脚本控制台功能。目前已经成功导入了Jenkins相关依赖包:
@GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases') @Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.377') @Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-api', version='1200.v8005c684b_a_c6') @Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-job', version='1254.v3f64639b_11dd') @Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-step-api', version='639.v6eca_cd8c04a_a_') import jenkins.model.Jenkins import hudson.Util import hudson.model.Job import org.jenkinsci.plugins.workflow.job.WorkflowJob String rootUrl = 'https://my.jenkins.com' String username = 'admin' String password = 'admin' // .. how to new a Jenkins instance here .. // i.e.: Jenkins jenkins = new Jenkins.instance( url, username, password ) // list all workflowjobs Jenkins.instance.getAllItems( WorkflowJob.class ).collect { it.fullName }
但我不知道怎么通过URL、用户名和密码创建Jenkins实例,实现像jenkins.model.Jenkins.instance.xxx这样的操作。另外我试过用jenkinsci/java-client-api创建JenkinsServer实例:
@GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases') @Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.377') @Grab(group='com.offbytwo.jenkins', module='jenkins-client', version='0.3.8') import com.offbytwo.jenkins.JenkinsServer String rootUrl = 'https://my.jenkins.com' String username = 'admin' String password = 'admin' JenkinsServer jenkins = new JenkinsServer( new URI(rootUrl), username, password ) jenkins.getJobs()
但这个API识别不了AbstractItem.class、WorkflowJob.class这类类,想问下有没有办法把com.offbytwo.jenkins.JenkinsServer转换成jenkins.model.Jenkins?
解决方案
首先明确:jenkins.model.Jenkins是Jenkins服务端运行时的核心类,它只能在Jenkins服务器本地的JVM里直接实例化调用,没办法通过远程URL直接创建这个类的实例——因为它绑定了Jenkins服务器的本地资源和运行环境,远程场景下没法直接复用这个类的API。
方案1:使用Jenkins远程API提交Groovy脚本(最贴近脚本控制台体验)
Jenkins脚本控制台本质是在服务器端执行Groovy代码,我们可以直接通过远程API提交脚本到服务器执行,这样就能完全复用jenkins.model.Jenkins等服务端类的API。示例代码:
@GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases') @Grab(group='org.apache.httpcomponents', module='httpclient', version='4.5.14') import org.apache.http.HttpEntity import org.apache.http.auth.AuthScope import org.apache.http.auth.UsernamePasswordCredentials import org.apache.http.client.CredentialsProvider import org.apache.http.client.methods.HttpPost import org.apache.http.entity.StringEntity import org.apache.http.impl.client.BasicCredentialsProvider import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClients import org.apache.http.util.EntityUtils String rootUrl = 'https://my.jenkins.com' String username = 'admin' String password = 'admin' String script = ''' import jenkins.model.Jenkins import org.jenkinsci.plugins.workflow.job.WorkflowJob Jenkins.instance.getAllItems(WorkflowJob.class).collect { it.fullName } ''' // 构建带认证的HTTP客户端 CredentialsProvider provider = new BasicCredentialsProvider() provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)) CloseableHttpClient client = HttpClients.custom().setDefaultCredentialsProvider(provider).build() try { HttpPost post = new HttpPost("${rootUrl}/scriptText") // 编码脚本内容并设置请求实体 String encodedScript = URLEncoder.encode(script, 'UTF-8') post.setEntity(new StringEntity("script=${encodedScript}", "application/x-www-form-urlencoded")) def response = client.execute(post) HttpEntity entity = response.getEntity() // 打印执行结果 println EntityUtils.toString(entity) } finally { client.close() }
这个方案直接模拟脚本控制台的行为,提交Groovy代码到服务器执行并返回结果,完全支持所有服务端类的API。
方案2:适配jenkins-client库实现需求(如果坚持用客户端库)
com.offbytwo.jenkins.JenkinsServer是基于Jenkins REST API封装的客户端,它本身不会直接映射服务端的AbstractItem、WorkflowJob等类。如果要用这个库获取流水线任务,可以通过REST API返回的_class字段来筛选:
@GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases') @Grab(group='com.offbytwo.jenkins', module='jenkins-client', version='0.3.8') import com.offbytwo.jenkins.JenkinsServer import com.offbytwo.jenkins.model.Job String rootUrl = 'https://my.jenkins.com' String username = 'admin' String password = 'admin' JenkinsServer jenkins = new JenkinsServer(new URI(rootUrl), username, password) // 过滤出流水线类型的任务(通过_class字段匹配) List<Job> workflowJobs = jenkins.getJobs().findAll { job -> job.get("_class") == "org.jenkinsci.plugins.workflow.job.WorkflowJob" } // 输出所有流水线任务的全名 workflowJobs.each { println it.fullName }
这种方式依赖Jenkins REST API返回的类型标识字段,虽然不能直接使用服务端的WorkflowJob类,但可以实现类似的筛选功能。
内容的提问来源于stack exchange,提问作者Marslo

