跳到主要内容

3、共享库

共享库

目录

[toc]

环境

  • 实验环境
jenkins/jenkins:2.346.3-2-lts-jdk11
gitee仓库/github仓库/gitlab仓库都行
  • 实验软件

链接:https://pan.baidu.com/s/12a9iRveUOUbQpSNAE7WhIw 提取码:0820 2023.4.11-共享库-代码

image-20230411211715046

1、共享库概述

共享库这并不是一个全新的概念,其实在编程语言Python中,我们可以将Python代码写到一个文件中,当代码数量增加,我们可以将代码打包成模块然后再以import的方式使用此模块中的方法。

在Jenkins中使用Groovy语法,共享库中存储的每个文件都是一个groovy的类每个文件(类)中包含一个或多个方法。每个方法包含groovy语句块

可以在Git等版本控制系统中创建一个项目用于存储共享库。共享流水线有助于减少冗余并保持代码整洁。

image-20230410132418409

库结构:

  • src: 类似于java的源码目录,执行流水线时会加载到class路径中。 //需要先导入才可以使用
  • vars: 存放全局变量脚本,小的功能函数。 //可以直接加载的
  • resources: 存放资源文件,类似于配置信息文件。

2、共享库定义

1.创建一个项目

devops06-jenkins-library

可以直接在github中创建一个公开类型的仓库,仓库名称自定义。公开类型的仓库是为了便于验证,也可以创建私有类型的,但是需要提前配置好仓库的认证凭据。

image-20230410125443419

2.创建目录结构

image-20230410132911036

src
vars
rsources

3.将函数写入共享库中

1、创建resources/config/config.json文件

image-20230410133719423

{
"id": 100,
"name": "devops"
}

2、创建src/og/devops/Common.groovy文件

image-20230411060852834

package org.devops

// define GetUserName
def GetUserNameByID(users,id){
for (i in users){
if (i["id"] == id){
return i["name"]
}
}
return "null"
}

3、创建vars/GetUserName.groovy文件

image-20230411061059239

// define GetUserName
def GetUserNameByID(users,id){
for (i in users){
if (i["id"] == id){
return i["name"]
}
}
return "null"
}

提交:(这里以main分支提交)

image-20230411061242543

image-20230411061306033

4.共享库的定义

image-20230411061858944

Jenkins系统配置 -> Global Pipeline Libraries

首先,我们为共享库设置一个名称 mylib自定义,无需与gitlab仓库一致),注意这个名称后续在Jenkinsfile中引用。 再设置一个默认的版本,这里的版本是分支的名称。我默认配置的是main版本。(github默认版本必须是main)

image-20230411062235324

⚠️ 注意:

  • 这里的Name不一定和刚才创建的仓库名称一样,只是一个别名而已;
  • 这里的Default version填的是仓库的分支名称;
  • 共享库是可以配置多个的!
  • 接下来我们配置**共享库的仓库地址,**我的仓库在gitlab中,所以这里我填写的是Git的方式。如果仓库是私有的方式,需要在jenkins的凭据中添加一个账号用于下载共享库。

image-20230411062317360

image-20230411062301224

点击Save

3、共享库使用

image-20230411195524142

测试1:基础使用共享库

  • 编写Jenkinsfile代码,并提交:

image-20230411063524144

@Library("mylib") _ 

pipeline {
agent any

stages{
stage("Test"){
steps{
script{
echo "hello world!"
}
}
}
}
}

提交:

image-20230411063548434


⚠️

==注意:这里出现一个gitlab报错的问题……在定义共享库配置后:说是无法解析刚才的仓库地址==

hudson.plugins.git.GitException: Command "git ls-remote -h -- http://440c1581aeec/root/devops06-jenkins-library.git" returned status code 128:
stdout:
stderr: fatal: unable to access 'http://440c1581aeec/root/devops06-jenkins-library.git/': Could not resolve host: 440c1581aeec

image-20230411071836594

  • 开始执行流水线:

这里再配置下流水线,让其使用gitlab里的仓库:

image-20230411072138462

image-20230411072208531

  • 运行后,这里会报错……

image-20230411072322055

  • 奇怪哇:

自己把这个字符串和本地机器做了域名解析,在自己pc上是可以正常拉取仓库的,但是jenkins是不行的……

image-20230411072422087

image-20230411072452101

这个应该是gitlab哪里的配置问题……

这里先进行搁置,此时用gitee来测试。
  • 在自己的gitee上创建相同的配置:

image-20230411072558255

  • 然后重新配置jenkins及流水线内容:

image-20230411072708681

image-20230411072731726

  • 再次运行,观察效果:

image-20230411072759312

看到,这次就成功了。😘

测试2:src目录里导包

编写Jenkinsfile代码:

image-20230411074106392

image-20230411073711351

@Library("mylib") _ 

//import Common.groovy
def common = new org.devops.Common()

users = [
["id": 1, "name": "jenkins1"],
["id": 2, "name": "jenkins2"],
["id": 3, "name": "jenkins3"],
]


pipeline {
agent any

stages{
stage("Test"){
steps{
script{
echo "hello world!"
name = common.GetUserNameByID(users,1)
print(name)
}
}
}
}
}

提交,并运行流水线。

image-20230411074131422

image-20230411074145754

符合预期。

测试3:vars里函数调用

  • 编写jenkins代码

错误版演示:

image-20230411075041137

image-20230411075103115

提交并运行流水线:

image-20230411075203751

可以看到会报错的。

  • 我们再来演示下正确版写法:

image-20230411075831846

call是固定写法:

image-20230411075854045

@Library("mylib") _ 

//import Common.groovy
def common = new org.devops.Common()

users = [
["id": 1, "name": "jenkins1"],
["id": 2, "name": "jenkins2"],
["id": 3, "name": "jenkins3"],
]


pipeline {
agent any

stages{
stage("Test"){
steps{
script{
echo "hello world!"
name = common.GetUserNameByID(users,1)
print(name)

echo "vars output demo"
name = GetUserName(users,2)
print(name)
}
}
}
}
}
  • 提交并运行:

image-20230411075807332

符合预期。

测试4:资源文件引用

  • 代码

image-20230411165214715

image-20230411165227422

@Library("mylib") _ 

//import Common.groovy
def common = new org.devops.Common()

users = [
["id": 1, "name": "jenkins1"],
["id": 2, "name": "jenkins2"],
["id": 3, "name": "jenkins3"],
]


pipeline {
agent any

stages{
stage("Test"){
steps{
script{
echo "src output demo"
name = common.GetUserNameByID(users,1)
print(name)

echo "vars output demo"
name = GetUserName(users,2) //注意:这里输出的是字符串数据
print(name)

echo "get resources"
data = libraryResource 'config/config.json'
println(data)

}
}
}
}
}
  • 提交并运行

image-20230411165134649

测试5:处理json数据

  • 安装pipeline util插件(安装了这个插件后,才能使用这些语法)

image-20230411165815653

image-20230411165707838

  • 代码

image-20230411170933536

@Library("mylib") _ 

//import Common.groovy
def common = new org.devops.Common()

users = [
["id": 1, "name": "jenkins1"],
["id": 2, "name": "jenkins2"],
["id": 3, "name": "jenkins3"],
]


pipeline {
agent any

stages{
stage("Test"){
steps{
script{
echo "src output demo"
name = common.GetUserNameByID(users,1)
print(name)

echo "vars output demo"
name = GetUserName(users,2)
print(name)


echo "get resources"
data = libraryResource 'config/config.json' //这里是字符串数据
println(data)

//这里是json数据
data_json = readJSON text: data
println(data_json["id"])

}
}
}
}
}
  • 运行

image-20230411170538769

4、代码汇总

Jenkinsfile

image-20230411212602091

@Library("mylib") _ 

//import Common.groovy
def common = new org.devops.Common()

users = [
["id": 1, "name": "jenkins1"],
["id": 2, "name": "jenkins2"],
["id": 3, "name": "jenkins3"],
]


pipeline {
agent any

stages{
stage("Test"){
steps{
script{
echo "src output demo"
name = common.GetUserNameByID(users,1)
print(name)

echo "vars output demo"
name = GetUserName(users,2)
print(name)


echo "get resources"
data = libraryResource 'config/config.json' //这里是字符串数据
println(data)

//这里是json数据
data_json = readJSON text: data
println(data_json["id"])

}
}
}
}
}

Common.groovy

image-20230411212647282

package org.devops

// define GetUserName
def GetUserNameByID(users,id){
for (i in users){
if (i["id"] == id){
return i["name"]
}
}
return "null"
}

GetUserName.groovy

image-20230411212711289

// define GetUserName
def call(users,id){
for (i in users){
if (i["id"] == id){
return i["name"]
}
}
return "null"
}

config.json

image-20230411212858260

{
"id": 100,
"name": "devops"
}

FAQ

TemplatingEngine实践(扩展)🍊

准备JTE代码

准备Librarys Resource仓库: 根目录例如gradlemaven都是单独的library, 目录下steps是我们具体定义的功能函数。

tstmp_20230411213132

准备配置Pipeline Template和Configuration Files:

pipeline_config.groovy

//加载的仓库
libraries{
sonarqube
gradle
}

// 环境变量
application_environments{
dev {
short_name = "t"
}
test
}

Jenkinsfile

pipeline {
agent {
label "master"
}

stages{
stage("build"){
steps{
build(dev.short_name)
build_test()
}
}
}
}

安装JTE插件

安装Templating Engine插件

tstmp_20230411213246

进入系统配置,配置插件:

tstmp_20230411213301

tstmp_20230411213312

Pipeline测试

创建一条Pipeline

tstmp_20230411213328

ConsoleOutput

Started by user unknown or anonymous
[JTE] Obtained Pipeline Configuration File (show)
[JTE] Pipeline Configuration Modifications (show)
[JTE] Obtained Template (show)
[JTE] Loading Library sonarqube (show)
[JTE] Loading Library gradle (show)
[JTE] Template Primitives are overwriting Jenkins steps with the following names: (show)
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/demo-jte-pipeline
[Pipeline] {
[Pipeline] stage
[Pipeline] { (build)
[JTE][Step - gradle/build.call(String)]
[Pipeline] echo
gradle build
[Pipeline] echo
t
[JTE][Step - gradle/build_test.call()]
[Pipeline] readJSON
[Pipeline] echo
{"name":"jenkins","id":"devopsvip"}
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

参考文档

https://www.jenkins.io/blog/2019/05/09/templating-engine/

https://jenkinsci.github.io/templating-engine-plugin/2.5/concepts/library-development/library-resources/

示例代码库:

https://jihulab.com/devopsvip/demo-jte-config

https://jihulab.com/devopsvip/demo-jte-lib

2023.4.11-TemplatingEngine实践(扩展)-测试代码

链接:https://pan.baidu.com/s/1C_RaCMCH5PxzNsQ2sVm_5g 提取码:0820 image-20230411213605195

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 微信二维码

x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号

《云原生架构师实战》

image-20230107215126971

🍀 个人主页:

https://onedayxyy.cn

image-20240604060532928

🍀 知识库:

https://onedayxyy.cn/docusaurus/

image-20240602215648594

🍀 博客:

http://47.100.215.163:8090/

image-20240602215637124

image-20240602215720712

🍀 csdn

https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎

https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!