# python-jenkins库 ## 简述 Python Jenkins是一个针对Jenkins REST API的Python包装器,旨在提供一种更传统的Python方式来控制Jenkins服务器。它提供了一个包含许多方便函数的高级API。 我们喜欢使用python-jenkins来自动化我们的Jenkins服务器。下面是一些你可以用它来做的事情: - 创建新的jobs - copy已存在的jobs - 删除jobs - 更新jobs - 获取jobs的构建信息 - 获取jenkins master的版本信息 - 获取jenkins插件信息 - 启动job开始构建 - 创建nodes - 启用或禁用nodes - 创建删除或重新配置视图 - 将服务器关机 - 查看运行的构建列表 - 删除构建 - 失败的工作空间 - 创建删除或更新folders - 设置下一个构建号 - 安装插件 - 其他 ## 安装 ``` (venv) D:\untitled2>pip install python-jenkins ``` ## API参考 [参考以及示例](https://python-jenkins.readthedocs.io/en/latest/api.html#jenkins.Jenkins.maybe_add_crumb) ### 异常错误变量 > jenkins api相关故障的通用异常类型。 ``` exceptionjenkins.JenkinsException ``` > 调用接收404的情况的特殊异常。 ``` exceptionjenkins.NotFoundException ``` > 一个特殊的异常,调用接收空响应的情况。 ``` exceptionjenkins.EmptyResponseException ``` > 一个特殊的异常,用于调用HTTP响应中断的情况。 ``` exceptionjenkins.BadHTTPException ``` > 在套接字超时的情况下调用的特殊异常。 ``` exceptionjenkins.TimeoutException ``` ## 实例类 ### 创建jenkins实例句柄 ``` class jenkins.Jenkins(url, username=None, password=None, timeout=, resolve=True) Parameters: url –jenkins服务器的url, str username – 用户名, str password – 密码, str timeout – 服务器连接超时时间(默认未设置), int resolve – 尝试解析和自动纠正API重定向。默认值:true, bool ``` **实例所有方法在失败时会抛出JenkinsException。** #### 通过job的name获取job信息字典 ``` get_job_info(name, depth=0, fetch_all_builds=False) Parameters: name – job名字, str depth – JSON 深度, int fetch_all_builds – 如果为真,将从Jenkins检索所有构建。否则,Jenkins将只返回最近的100个构建。这是以额外的API调用为代价的,它可能会返回大量的数据. bool Returns: job信息字典,dict ``` #### 通过正则获取包含匹配的名称的工作信息列表 ``` get_job_info_regex(pattern, depth=0, folder_depth=0) Parameters: pattern – 正则表达式字符串, str depth – JSON 深度, int folder_depth – 搜索文件夹级别的深度,int Returns: List of jobs info, list ``` #### 使用API返回job的名称 ``` get_job_name(name) Parameters: name – Job name, str Returns: Name of job or None ``` **可用于快速验证job是否存在或是否可访问,而不会对服务器端造成太大压力。** #### 以更易读的格式打印工作信息 ``` debug_job_info(job_name) ``` #### 获取http响应体 ``` jenkins_open(req, add_crumb=True, resolve_auth=True) Returns: str ``` #### 获取关于要创建的作业队列信息 ``` get_queue_item(number, depth=0) Parameters: name – queue number, int Returns: dictionary of queued information, dict ``` 如果队列中的条目仍在等待执行器,则返回的dict将有一个“why”键。 如果队列中的项正在执行程序上运行,或者已完成运行,返回的字典将具有一个“可执行”键。使用它来确定作业编号/ URL。 #### 获取构建信息字典 ``` get_build_info(name, number, depth=0) Parameters: name – Job name, str number – Build number, int depth – JSON depth, int Returns: dictionary of build information, dict ``` 示例: ``` >>> next_build_number = server.get_job_info('build_name')['nextBuildNumber'] >>> output = server.build_job('build_name') >>> from time import sleep; sleep(10) >>> build_info = server.get_build_info('build_name', next_build_number) >>> print(build_info) {u'building': False, u'changeSet': {u'items': [{u'date': u'2011-12-19T18:01:52.540557Z', u'msg': u'test', u'revision': 66, u'user': u'unknown', u'paths': [{u'editType': u'edit', u'file': u'/branches/demo/index.html'}]}], u'kind': u'svn', u'revisions': [{u'module': u'http://eaas-svn01.i3.level3.com/eaas', u'revision': 66}]}, u'builtOn': u'', u'description': None, u'artifacts': [{u'relativePath': u'dist/eaas-87-2011-12-19_18-01-57.war', u'displayPath': u'eaas-87-2011-12-19_18-01-57.war', u'fileName': u'eaas-87-2011-12-19_18-01-57.war'}, {u'relativePath': u'dist/eaas-87-2011-12-19_18-01-57.war.zip', u'displayPath': u'eaas-87-2011-12-19_18-01-57.war.zip', u'fileName': u'eaas-87-2011-12-19_18-01-57.war.zip'}], u'timestamp': 1324317717000, u'number': 87, u'actions': [{u'parameters': [{u'name': u'SERVICE_NAME', u'value': u'eaas'}, {u'name': u'PROJECT_NAME', u'value': u'demo'}]}, {u'causes': [{u'userName': u'anonymous', u'shortDescription': u'Started by user anonymous'}]}, {}, {}, {}], u'id': u'2011-12-19_18-01-57', u'keepLog': False, u'url': u'http://eaas-jenkins01.i3.level3.com:9080/job/build_war/87/', u'culprits': [{u'absoluteUrl': u'http://eaas-jenkins01.i3.level3.com:9080/user/unknown', u'fullName': u'unknown'}], u'result': u'SUCCESS', u'duration': 8826, u'fullDisplayName': u'build_war #87'} ``` 可以根据返回的ret["building"]来判断当前job是否还在构建中,如果为true,就说明还在构建中,否则就说明已经构建完成 可以根据返回的ret["result"]来判断构建是否成功,成功返回SUCCESS,失败返回FAILURE #### 获取构建环境变量 ``` get_build_env_vars(name, number, depth=0) Parameters: name – Job name, str number – Build number, int depth – JSON depth, int Returns: dictionary of build env vars, dict or None for workflow jobs, or if InjectEnvVars plugin not installed ``` #### 获取队列中的job信息 ``` get_queue_info() Returns: list of job dictionaries, [dict] ``` 示例 ``` >>> queue_info = server.get_queue_info() >>> print(queue_info[0]) {u'task': {u'url': u'http://your_url/job/my_job/', u'color': u'aborted_anime', u'name': u'my_job'}, u'stuck': False, u'actions': [{u'causes': [{u'shortDescription': u'Started by timer'}]}], u'buildable': False, u'params': u'', u'buildableStartMilliseconds': 1315087293316, u'why': u'Build #2,532 is already in progress (ETA:10 min)', u'blocked': True} ``` #### 根据buildid取消在排队的构建 ``` cancel_queue(id) Parameters: id – Jenkins job id number for the build, int ``` #### 获取jenkins机器的info信息 这些信息包括作业列表和视图信息,可用于检索作业文件夹等项目的信息。 ``` get_info(item='', query=None) Parameters: item – item to get information about on this Master query – xpath to extract information about on this Master Returns: dictionary of information about Master or item, dict ``` 示例 ``` >>> info = server.get_info() >>> jobs = info['jobs'] >>> print(jobs[0]) {u'url': u'http://your_url_here/job/my_job/', u'color': u'blue', u'name': u'my_job'} ``` #### 获取验证用户信息 获取关于向Jenkins验证的用户帐户的信息。这是一种验证凭证是否正确的简单方法。 ``` get_whoami(depth=0) Returns: Information about the current user dict ``` 示例: ``` >>> me = server.get_whoami() >>> print me['fullName'] >>> 'John' ``` #### 获取jenkins版本信息 ``` get_version() Returns: This master’s version number str ``` 示例: ``` >>> info = server.get_version() >>> print info >>> 1.541 ``` #### 获取jenkins已安装插件信息 该方法检索安装在master上的每个插件的信息,并以JSON格式返回原始插件数据。 ``` get_plugins_info(depth=2) Deprecated since version 0.4.9: Use get_plugins() instead. Parameters: depth – JSON depth, int Returns: info on all plugins [dict] ``` 示例: ``` >>> info = server.get_plugins_info() >>> print(info) [{u'backupVersion': None, u'version': u'0.0.4', u'deleted': False, u'supportsDynamicLoad': u'MAYBE', u'hasUpdate': True, u'enabled': True, u'pinned': False, u'downgradable': False, u'dependencies': [], u'url': u'http://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin', u'longName': u'Gearman Plugin', u'active': True, u'shortName': u'gearman-plugin', u'bundled': False}, ..] ``` #### 获取jenkins上已安装指定名字插件信息 该方法检索关于特定插件的信息,并以JSON格式返回原始插件数据。传入的插件名称(短或长)必须精确匹配。 调用这个方法将会在每次调用中查询Jenkins的所有插件信息。如果你需要检索多个插件的信息,建议使用get_plugins(),它将返回一个多键字典,可以通过插件的长或短名称访问它。 ``` get_plugin_info(name, depth=2) Parameters: name – Name (short or long) of plugin, str depth – JSON depth, int Returns: a specific plugin dict ``` 示例: ``` >>> info = server.get_plugin_info("Gearman Plugin") >>> print(info) {u'backupVersion': None, u'version': u'0.0.4', u'deleted': False, u'supportsDynamicLoad': u'MAYBE', u'hasUpdate': True, u'enabled': True, u'pinned': False, u'downgradable': False, u'dependencies': [], u'url': u'http://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin', u'longName': u'Gearman Plugin', u'active': True, u'shortName': u'gearman-plugin', u'bundled': False} ``` #### 使用helper类获取插件信息 使用helper类返回插件信息以进行版本比较 该方法检索关于所有已安装插件的信息,并使用一个Plugin helper类来简化版本比较。也使用多键字典允许通过短或长名称进行检索。 当打印/转储数据时,版本将透明地返回一个unicode字符串,这正是以前API返回的内容。 ``` get_plugins(depth=2) Parameters: depth – JSON depth, int Returns: info on all plugins [dict] ``` 示例: ``` >>> j = Jenkins() >>> info = j.get_plugins() >>> print(info) {('gearman-plugin', 'Gearman Plugin'): {u'backupVersion': None, u'version': u'0.0.4', u'deleted': False, u'supportsDynamicLoad': u'MAYBE', u'hasUpdate': True, u'enabled': True, u'pinned': False, u'downgradable': False, u'dependencies': [], u'url': u'http://wiki.jenkins-ci.org/display/JENKINS/Gearman+Plugin', u'longName': u'Gearman Plugin', u'active': True, u'shortName': u'gearman-plugin', u'bundled': False}, ...} ``` #### 获取jobs列表(可限定试图) 每个作业都是一个带有' name ', ' url ', ' color '和' fullname '键的字典。 如果view_name参数存在,作业列表将仅限于在指定视图中配置的作业。在本例中,作业字典' fullname '键将等于作业名称。 ``` get_jobs(folder_depth=0, view_name=None) Parameters: folder_depth – Number of levels to search, int. By default 0, which will limit search to toplevel. None disables the limit. view_name – Name of a Jenkins view for which to retrieve jobs, str. By default, the job list is not limited to a specific view. Returns: list of jobs, [{str: str, str: str, str: str, str: str}] ``` 示例: ``` >>> jobs = server.get_jobs() >>> print(jobs) [{ u'name': u'all_tests', u'url': u'http://your_url.here/job/all_tests/', u'color': u'blue', u'fullname': u'all_tests' }] ``` #### 获取所有jobs列表 将所有作业的列表递归到给定的文件夹深度。 每个作业都是一个带有' name ', ' url ', ' color '和' fullname '键的字典。 ``` get_all_jobs(folder_depth=None) Parameters: folder_depth – Number of levels to search, int. By default None, which will search all levels. 0 limits to toplevel. Returns: list of jobs, [ { str: str} ] ``` 在具有许多文件夹的实例中,使用run_script方法检索所有作业可能更有效。 示例: ``` server.run_script(""" import groovy.json.JsonBuilder; // get all projects excluding matrix configuration // as they are simply part of a matrix project. // there may be better ways to get just jobs items = Jenkins.instance.getAllItems(AbstractProject); items.removeAll { it instanceof hudson.matrix.MatrixConfiguration }; def json = new JsonBuilder() def root = json { jobs items.collect { [ name: it.name, url: Jenkins.instance.getRootUrl() + it.getUrl(), color: it.getIconColor().toString(), fullname: it.getFullName() ] } } // use json.toPrettyString() if viewing println json.toString() """) ``` #### 拷贝jenkins job 当此作业的源文件夹和目标文件夹不相同时将引发异常。 ``` copy_job(from_name, to_name) Parameters: from_name – Name of Jenkins job to copy from, str to_name – Name of Jenkins job to copy to, str Throws: JenkinsException whenever the source and destination folder are not the same ``` #### 重命名job 当此作业的源文件夹和目标文件夹不相同时将引发异常。 ``` rename_job(from_name, to_name) Parameters: from_name – Name of Jenkins job to rename, str to_name – New Jenkins job name, str Throws: JenkinsException whenever the source and destination folder are not the same ``` #### 删除job ``` delete_job(name) Parameters: name – Name of Jenkins job, str ``` #### 启用job ``` enable_job(name) Parameters: name – Name of Jenkins job, str ``` #### 禁用job ``` disable_job(name) To re-enable, call Jenkins.enable_job(). Parameters: name – Name of Jenkins job, str ``` #### 设置job下一次构建号 当前的下一个构建号包含在使用Jenkins.get_job_info()["nextBuildNumber"]检索的工作信息中。如果指定的下一个构建号小于上一个构建号,Jenkins将忽略该请求。 **请注意,必须安装下一个构建号插件才能启用此功能。** ``` set_next_build_number(name, number) Parameters: name – Name of Jenkins job, str number – Next build number to set, int ``` 示例: ``` >>> next_bn = server.get_job_info('job_name')['nextBuildNumber'] >>> server.set_next_build_number('job_name', next_bn + 50) ``` #### 检查job是否存在 ``` job_exists(name) Parameters: name – Name of Jenkins job, str Returns: True if Jenkins job exists ``` #### 获取jobs数量 ``` jobs_count() Returns: Total number of jobs, int ``` 在具有许多文件夹的实例中,使用run_script方法检索作业的总数可能更有效。 示例 ``` # get all projects excluding matrix configuration # as they are simply part of a matrix project. server.run_script( "print(Hudson.instance.getAllItems(" " hudson.model.AbstractProject).count{" " !(it instanceof hudson.matrix.MatrixConfiguration)" " })") ``` #### 如果jobs不存在则引发异常 ``` assert_job_exists(name, exception_message='job[%s] does not exist') Parameters: name – Name of Jenkins job, str exception_message – Message to use for the exception. Formatted with name Throws: JenkinsException whenever the job does not exist ``` #### 创建job ``` create_job(name, config_xml) Parameters: name – Name of Jenkins job, str config_xml – config file text, str ``` #### 获取现有jenkins job的配置 ``` get_job_config(name) Parameters: name – Name of Jenkins job, str Returns: job configuration (XML format) ``` #### 更改现有Jenkins job的配置 要创建新作业,请参见Jenkins.create_job()。 ``` reconfig_job(name, config_xml) Parameters: name – Name of Jenkins job, str config_xml – New XML configuration, str ``` #### 获取触发构建作业的URL 经过身份验证的设置可能需要在服务器端配置一个令牌。 使用两个成员元组的列表来提供具有多选择选项的参数。 ``` build_job_url(name, parameters=None, token=None) Parameters: name – Name of Jenkins job, str parameters – parameters for job, or None., dict or list of two membered tuples token – (optional) token for building job, str Returns: URL for building job ``` #### 触发作业job 此方法返回一个队列项号,您可以将其传递给Jenkins.get_queue_item()。注意,该队列号仅在作业完成后的大约5分钟内有效,因此您应该尽快获取/轮询队列信息,以确定作业的URL。 如果job有需要参数,可以以json格式传入,如下: ``` server.build_job('api-test', {'param1': 'test value 1', 'param2': 'test value 2'}) ``` 示例 ``` build_job(name, parameters=None, token=None) Parameters: name – name of job parameters – parameters for job, or None, dict token – Jenkins API token Returns: int queue item ``` 示例 ``` if __name__ == '__main__': j = jenkins.Jenkins("http://192.168.253.11:8080","xieys","123456") # print(j.get_all_jobs()) 获取所有jobs a = j.build_job("test") print(j.get_queue_item(a)) 输出 {'_class': 'hudson.model.Queue$WaitingItem', 'actions': [{'_class': 'hudson.model.CauseAction', 'causes': [{'_class': 'hudson.model.Cause$UserIdCause', 'shortDescription': 'Started by user xieys', 'userId': 'xieys', 'userName': 'xieys'}]}], 'blocked': False, 'buildable': False, 'id': 124, 'inQueueSince': 1638266803144, 'params': '', 'stuck': False, 'task': {'_class': 'hudson.model.FreeStyleProject', 'name': 'test', 'url': 'http://192.168.253.11:8080/job/test/', 'color': 'red'}, 'url': 'queue/item/124/', 'why': 'In the quiet period. Expires in 4.9 sec', 'timestamp': 1638266808144} ``` #### 在jenkins主机上或指定的节点上执行groovy脚本 ``` run_script(script, node=None) Parameters: script – The groovy script, string node – Node to run the script on, defaults to None (master). Returns: The result of the script run. ``` 示例 ``` >>> info = server.run_script("println(Jenkins.instance.pluginManager.plugins)") >>> print(info) u'[Plugin:windows-slaves, Plugin:ssh-slaves, Plugin:translation, Plugin:cvs, Plugin:nodelabelparameter, Plugin:external-monitor-job, Plugin:mailer, Plugin:jquery, Plugin:antisamy-markup-formatter, Plugin:maven-plugin, Plugin:pam-auth]' ``` #### 安装插件 从Jenkins公共存储库http://repo.jenkins-ci.org/repo/org/jenkins-ci/plugins中安装插件及其依赖项 ``` install_plugin(name, include_dependencies=True) Parameters: name – The plugin short name, string include_dependencies – Install the plugin’s dependencies, bool Returns: Whether a Jenkins restart is required, bool ``` 示例 ``` >>> info = server.install_plugin("jabber") >>> print(info) True ``` #### 根据buildid暂停正在运行的job ``` stop_build(name, number) Parameters: name – Name of Jenkins job, str number – Jenkins build number for the job, int ``` #### 根据buildid 删除此次构建 ``` delete_build(name, number) Parameters: name – Name of Jenkins job, str number – Jenkins build number for the job, int ``` #### 根据job name清理工作空间 这里需要修改下源码,修改jenkins包下的__init__.py文件,大约在1426行,修改如下: ``` 原来的代码 self.jenkins_open(requests.Request('POST', self._build_url(WIPEOUT_JOB_WORKSPACE, locals()), b'')) 修改后的代码 self.jenkins_open(requests.Request('POST', self._build_url(WIPEOUT_JOB_WORKSPACE, locals()))) ``` 方法签名 ``` wipeout_job_workspace(name) Parameters: name – Name of Jenkins job, str ``` #### 获取正在运行的构建列表 每个构建都是一个具有键' name '、' number '、' url '、' node '和' executor '的字典。 ``` get_running_builds() Returns: List of builds, [ { str: str, str: int, str:str, str: str, str: int} ] ``` 示例 ``` >>> builds = server.get_running_builds() >>> print(builds) [{'node': 'foo-slave', 'url': 'https://localhost/job/test/15/', 'executor': 0, 'name': 'test', 'number': 15}] ``` #### 获取连接到主节点的节点列表 每个节点都是一个带有键' name '和' offline '的字典。 ``` get_nodes(depth=0) Returns: List of nodes, [ { str: str, str: bool} ] ``` #### 获取节点info信息字典 ``` get_node_info(name, depth=0) Parameters: name – Node name, str depth – JSON depth, int Returns: Dictionary of node info, dict ``` #### 检查节点是否存在 ``` node_exists(name) Parameters: name – Name of Jenkins node, str Returns: True if Jenkins node exists ``` #### 检查节点是否存在,不存在引发异常 ``` assert_node_exists(name, exception_message='node[%s] does not exist') Parameters: name – Name of Jenkins node, str exception_message – Message to use for the exception. Formatted with name Throws: JenkinsException whenever the node does not exist ``` #### 删除jenkins节点 ``` delete_node(name) Parameters: name – Name of Jenkins node, str ``` #### 禁用节点 ``` disable_node(name, msg='') Parameters: name – Jenkins node name, str msg – Offline message, str ``` #### 启用节点 ``` enable_node(name) Parameters: name – Jenkins node name, str ``` #### 创建节点 ``` create_node(name, numExecutors=2, nodeDescription=None, remoteFS='/var/lib/jenkins', labels=None, exclusive=False, launcher='hudson.slaves.CommandLauncher', launcher_params={}) Parameters: name – name of node to create, str numExecutors – number of executors for node, int nodeDescription – Description of node, str remoteFS – Remote filesystem location to use, str labels – Labels to associate with node, str exclusive – Use this node for tied jobs only, bool launcher – The launch method for the slave, jenkins.LAUNCHER_COMMAND, jenkins.LAUNCHER_SSH, jenkins.LAUNCHER_JNLP, jenkins.LAUNCHER_WINDOWS_SERVICE launcher_params – Additional parameters for the launcher, dict ``` #### 获取节点的配置信息 ``` get_node_config(name) Parameters: name – Jenkins node name, str ``` #### 重新配置节点信息 ``` reconfig_node(name, config_xml) Parameters: name – Jenkins node name, str config_xml – New XML configuration, str ``` #### 获取构建控制台日志 ``` get_build_console_output(name, number) Parameters: name – Job name, str number – Build number, int Returns: Build console output, str ``` #### 使用api返回视图名称 可用于快速验证视图是否存在或是否可访问,而不会对服务器端造成太大压力。 ``` get_view_name(name) Parameters: name – View name, str Returns: Name of view or None ``` #### 判断视图是否存在,不存在报异常 ``` assert_view_exists(name, exception_message='view[%s] does not exist') Parameters: name – Name of Jenkins view, str exception_message – Message to use for the exception. Formatted with name Throws: JenkinsException whenever the view does not exist ``` #### 判断视图是否存在 每个视图都是一个带有' name '和' url '键的字典。 ``` get_views() Returns: list of views, [ { str: str} ] ``` #### 删除jenkins视图 ``` delete_view(name) Parameters: name – Name of Jenkins view, str ``` #### 创建jenkins视图 ``` create_view(name, config_xml) Parameters: name – Name of Jenkins view, str config_xml – config file text, str ``` #### 修改视图配置 要创建新视图,请参见Jenkins.create_view()。 ``` reconfig_view(name, config_xml) Parameters: name – Name of Jenkins view, str config_xml – New XML configuration, str ``` #### promotion相关 省略,[参考](https://python-jenkins.readthedocs.io/en/latest/api.html#jenkins.Jenkins.maybe_add_crumb) #### 获取视图配置 ``` get_view_config(name) Parameters: name – Name of Jenkins view, str Returns: view configuration (XML format) ``` #### 关闭jenkins 不会启动新的构建,允许在服务器关闭之前完成正在运行的构建。 ``` quiet_down() ``` #### 等待jenkins进入正常模式 ``` wait_for_normal_op(timeout) Parameters: timeout – number of seconds to wait, int Note this is not the same as the connection timeout set via __init__ as that controls the socket timeout. Instead this is how long to wait until the status returned. Returns: True if Jenkins became ready in time, False otherwise. ``` 将超时设置为小于配置的连接超时可能导致在返回之前至少等待连接超时的时间长度。建议这里的超时至少应该与任何设置的连接超时一样长。