# 前言

之前写过一篇文章介绍通过接口获取到数据来渲染构建过程中的动态参数,详见:Jenkins 中 pipeline 对接 CMDB 接口获取主机列表的发布实践 (opens new window)。那么既然能够通过接口渲染数据,是否可以直接在 activity choice 参数的 groovy 脚本中直接通过 MySQL 来实现动态参数的需求呢。

答案是可以的,只不过,一开始我没有料想到,这条路走的是如此曲折。

前后折腾了两次,花费了很多精力去寻找解决方案,最后终于算是摸索出来了一条可行的路。

赶快分享,不在话下!

# 环境

也许不同的 Jenkins 版本,或者插件版本在使用此功能的时候,会遇到与我不一样的问题,或者甚至压根儿不会遇到问题,这都说不准,具体你还要根据你的实际现状来测试,来验证,来观测。

那么我使用的环境基本信息如下:

我习惯使用 Tomcat 部署 war 包的形式来部署 Jenkins。

# 准备数据

因为需要与数据库交互,因此这里需要先有一个数据库,并准备一些基础数据。

创建数据库:

CREATE DATABASE IF NOT EXISTS jkdata DEFAULT CHARACTER SET utf8mb4;

1

创建用户表:

CREATE TABLE jkdata.users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50),
    department VARCHAR(50)
);

1
2
3
4
5

添加几个测试用户:

INSERT INTO jkdata.users (username, department) VALUES ('zhangsan', 'ops');
INSERT INTO jkdata.users (username, department) VALUES ('lisi', 'ops');
INSERT INTO jkdata.users (username, department) VALUES ('wangwu', 'test');
INSERT INTO jkdata.users (username, department) VALUES ('zhaoliu', 'test');

1
2
3
4

我们的需求是先有一个选项参数,用于指定部门信息,然后动态参数通过查询数据库,列出对应部门的用户。

# 代码

经过一些检索实验,我这边调试后的代码如下:

properties([
    parameters([
        choice(
                name: 'department',
                choices: ['ops','test'],
                description: "ops==运维组<br>test==测试组"
        ),
        [
            $class: 'CascadeChoiceParameter',
            choiceType: 'PT_RADIO',
            name: 'username',
            description: "请选择对应的用户",
            referencedParameters: 'department',
            filterable: true,
            script:
                [
                    $class: 'GroovyScript',
                    fallbackScript: [
                        classpath: [],
                        sandbox: true,
                        script: "return['An error occured']"
                    ],
                    script: [
                        classpath: [],
                        sandbox: true,
                        script:
                            '''
import groovy.sql.Sql

def output = []

def sql = Sql.newInstance('jdbc:mysql://192.168.1.1:3306/jkdata', 'root', 'password', 'com.mysql.jdbc.Driver')
String sqlString = "SELECT DISTINCT username FROM user WHERE department = \'${department}\'"
    sql.eachRow(sqlString){ row ->
        output.push(row[0])
    }
return output
                                            '''
                    ]
                 ]
         ]
    ])
])

pipeline {
    agent any
    stages {
        stage("执行") {
            steps {
                sh '''
                    println"""
                        部门为: ${department}
                        用户为: ${username}
                    """
                '''
            }
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

前边使用了选项参数来写死了部门信息,下边用户信息则是根据选择的部门,通过查询数据库而将符合条件的用户列出来。

# 核心代码踩坑

里边的核心代码是:

import groovy.sql.Sql

def output = []

def sql = Sql.newInstance('jdbc:mysql://192.168.1.1:3306/jkdata', 'root', 'password', 'com.mysql.jdbc.Driver')
String sqlString = "SELECT DISTINCT username FROM user WHERE department = \'${department}\'"
    sql.eachRow(sqlString){ row ->
        output.push(row[0])
    }
return output

1
2
3
4
5
6
7
8
9
10

调试的过程就是这段代码踩坑的过程。主要问题出在 MySQL 的驱动上,我们可以把如上代码,来到 Jenkins 的 系统设置Script Console 中,尝试运行一下,然后就遇到了如下错误:

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1420)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1228)
	at java.base/java.lang.Class.forName0(Native Method)

1
2
3
4

如下图:

就是这样一个错误,我查遍了全网,进行了大量的阅读浏览,基本上都是货不对板的解决方案,或者不够详尽。

问题似乎不复杂,无非就是 Jenkins 在运行 groovy 脚本的时候,无法正确加载到驱动,那么,如何才能解决这个驱动问题呢?

直到经过了上百个网页浏览之后,我遇到了这样一篇文章:Jenkins 工程中 SQL 语句执行的方法 (opens new window) 里边介绍了,需要下载 com.mysql.jdbc_5.1.38.jar,然后将 jar 包放到 jenkins 的 lib 目录当中。

接下来问题又来了,文章只说了下载这个包,但没有直接放下载链接,经过检索之后,我发现可以通过这个链接下载这个包: http://www.java2s.com/Code/Jar/c/Downloadcommysqljdbc515jar.htm

这个链接下载的是 com.mysql.jdbc_5.1.15.jar 版本的,不过实测仍旧能够使用。

我的 jenkins 的 lib 路径是在 /usr/local/tomcat/webapps/ROOT/WEB-INF/lib,将下载的 jar 放到这个目录下,然后 重启 Jenkins,之后再到 Script Console 运行脚本,可以看到有结果了:

# 效果呈现

当代码调试通过之后,就可以将如上 groovy 创建为项目,然后运行项目,查看效果。

嗯,舒服!!

# 最后

虽然现在跑通了,但这里边我仍有一些疑惑,如果有人找到了答案,欢迎在评论区一块儿交流:

  • 在 activity choice 插件的参数当中,有一个参数项是 classpath,看起来像是能自定义 jar 包,但我做了许多尝试,都没能成功。
  • 上边的 groovy 脚本中的部门信息是通过选项参数写死的,你如果有兴趣让这个信息也通过数据库取出,那你可以尝试改造一些 groovy 来实现。