實現Jenkinsfile與Json的轉換
最近在做個需求,需要支持Jenkinsfile和json的轉換。
方法1:使用現有的jenkins插件
參考的是這篇文章。下面介紹一下將插件打包成鏡像的步驟:
-
本地安裝jdk和maven,jdk建議采用的版本為8(該工程會依賴一個名為
tools.jar
的包,jdk 9之后移除了該包)如果本地沒有找到
tools.jar
,可以下載一個1.8版本的jdk,然后在pom.xml
中增加如下依賴<dependency> <groupId>jdk.tools</groupId> <artifactId>jdk.tools</artifactId> <version>1.8.0</version> <scope>system</scope> <systemPath>/root/jdk1.8.0_271/lib/tools.jar</systemPath> </dependency>
-
clone pipeline-model-definition-plugin工程
-
在/root/.m2/目錄下創建
settings.xml
,內容來自Jenkins官方:<settings> <pluginGroups> <pluginGroup>org.jenkins-ci.tools</pluginGroup> </pluginGroups> <profiles> <!-- Give access to Jenkins plugins --> <profile> <id>jenkins</id> <activation> <activeByDefault>true</activeByDefault> <!-- change this to false, if you don't like to have it on per default --> </activation> <repositories> <repository> <id>repo.jenkins-ci.org</id> <url>https://repo.jenkins-ci.org/public/</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>repo.jenkins-ci.org</id> <url>https://repo.jenkins-ci.org/public/</url> </pluginRepository> </pluginRepositories> </profile> </profiles> <mirrors> <mirror> <id>repo.jenkins-ci.org</id> <url>https://repo.jenkins-ci.org/public/</url> <mirrorOf>m.g.o-public</mirrorOf> </mirror> </mirrors> </settings>
-
執行
mvn install
進行編譯 -
由於主要用到的是Jenkinsfile和json之間的轉換關系,因此主要用的是如下兩個REST API:
-
Conversion to JSON representation from Jenkinsfile
- URL:
JENKINS_URL/pipeline-model-converter/toJson
- Parameters:
jenkinsfile
- theJenkinsfile
contents - Info: Takes a
Jenkinsfile
and converts it to the JSON representation for itspipeline
step. - Returns: JSON with a
result
field that will either besuccess
orfailure
. Ifsuccess
, the JSON representation will be in thejson
field. Iffailure
, there'll be an additional array in theerrors
field of the error messages encountered.
- URL:
-
Conversion to Jenkinsfile from JSON representation
- URL:
JENKINS_URL/pipeline-model-converter/toJenkinsfile
- Parameters:
json
- the JSON representation of the model - Info: Takes the JSON representation of the model and converts it to the contents for a
Jenkinsfile
invoking thepipeline
step. - Returns: JSON with a
result
field that will either besuccess
orfailure
. Ifsuccess
, theJenkinsfile
contents will be in thejenkinsfile
field. Iffailure
, there'll be an additional array in theerrors
field of the error messages encountered.
- URL:
上述兩個API在
pipeline-model-definition-plugin/pipeline-model-definition
目錄下,因此在該目錄下直接運行:mvn hpi:run -Dhost=0.0.0.0 -Djetty.port=8080
即可。 -
-
將json轉換為Jenkinsfile的操作如下:
完整的返回值如下:
{ "status": "ok", "data": { "result": "success", "json": { "pipeline": { "stages": [ { "name": "Hello", "branches": [ { "name": "default", "steps": [ { "name": "echo", "arguments": [ { "key": "message", "value": { "isLiteral": true, "value": "Hello World" } } ] } ] } ] } ], "agent": { "type": "any" } } } } }
-
將Jenkinsfile轉換為json的操作如下
-
制作容器鏡像時,只需要將本地工程和
/root/.m2
上傳到容器,生成對應的鏡像即可,下面Dockerfile假設生成的鏡像為pipeline-model-definition-plugin:latest
FROM pipeline-model-definition-plugin:latest WORKDIR /usr/pipeline-model-definition-plugin/pipeline-model-definition ENV PATH=$PATH:/usr/local/bin/maven-3.6.3/bin ENTRYPOINT ["sh", "-c", "mvn hpi:run -Dhost=0.0.0.0"]
我自己打包了一個鏡像:
docker pull quay.io/woodliu/pipeline-model-definition-plugin
需要注意的是,本插件提供的轉換API toJenkinsfile和toJson並不是萬能的,只能支持jenkins標准的參數類型,例如對於gitParameter
這樣的參數就無法解析(擴展功能),一種解決方式是獨立解析擴展的參數,然后將其插入解析好的標准JenkinsFile中;另外一個方式就是寫一個jenkinsfile的解析器。
參考
-
mvn hpi的命令可以參考官方文檔
-
可以運行
mvn hpi:hpi
生成對應的hpi
文件,如:/pipeline-model-definition-plugin/pipeline-model-definition/target/pipeline-model-definition.hpi
方法2:解析原生的jenkinsfile文件
在GitHub上有一個支持jenkinsfile解析的項目,該項目使用rust的pest crate來編寫jenkinsfile的語法,支持對jenkinsfile的格式驗證。Pest官方文檔中給出了一個非常好的對json語法的解析例子,主要是使用遞歸的方式來解析語法。
pest官方提供了一個編輯器,可以使用該編輯器查看經過pest解析之后的字段,對了解pest的工作方式非常有用。如,使用jdp項目提供的pest文件解析如下jenkinsfile:
pipeline {
agent {
docker {
reuseNode true
image 'maven:3-alpine'
label 'my-defined-label'
args '-v /tmp:/tmp'
registryUrl 'https://myregistry.com/'
registryCredentialsId 'myPredefinedCredentialsInJenkins'
}
}
stages {
stage('Build') {
steps { sh 'make' }
}
}
}
對應的解析結果如下:
- preceeding_junk: ""
- opening_brace: "{"
- agentDecl > agentBlock
- opening_brace: "{"
- dockerAgent
- opening_brace: "{"
- bool: "true"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "maven:3-alpine"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "my-defined-label"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "-v /tmp:/tmp"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "https://myregistry.com/"
- single_quote: "\'"
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "myPredefinedCredentialsInJenkins"
- single_quote: "\'"
- closing_brace: "}"
- closing_brace: "}"
- stagesDecl
- opening_brace: "{"
- stage
- string > single_quoted
- single_quote: "\'"
- inner_single_str: "Build"
- single_quote: "\'"
- opening_brace: "{"
- stepsDecl
- opening_brace: "{"
- step > simple_step
- IDENT: "sh"
- args > string > single_quoted
- single_quote: "\'"
- inner_single_str: "make"
- single_quote: "\'"
- closing_brace: "}"
- closing_brace: "}"
- closing_brace: "}"
- closing_brace: "}"
- ending_junk: ""
- EOI: ""
Pest語法重點標注:
當使用靜默規則時,解析結果中將不會出現該規則字段。當解析下面規則時,解析結果中將不會存在silent,即
parsed.as_rule()
中不會存在silentsilent = _{ ... }
當使用原子語法時,整個規則體將視為一個規則,如double_quoted = ${ (quote ~ inner_double_str ~ quote) },在解析時會將
quote ~ inner_double_str ~ quote
視為一個規則,而不是三個。這有利於獲取一段完整的字符串。atomic = @{ ... } compound_atomic = ${ ... }
我嘗試使用該項目解析jenkinsfile,但發現實現起來太過復雜,且rust和jenkinsFile的語法也是一言難盡。如下,當step中帶括號和不帶括號混用時會導致解析錯誤。
steps {
echo 'test'
dir('command') {
sh "sh ./saas.sh ${params.channel} ${params.buildType} "
}
}
有精力的大神可以在此基礎上實現解析JenkinsFile的功能。
參考
- pest文檔