jenkins:實現Jenkinsfile與Json的轉換


實現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 - the Jenkinsfile contents
      • Info: Takes a Jenkinsfile and converts it to the JSON representation for its pipeline step.
      • Returns: JSON with a result field that will either be success or failure. If success, the JSON representation will be in the json field. If failure, there'll be an additional array in the errors field of the error messages encountered.
    • 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 the pipeline step.
      • Returns: JSON with a result field that will either be success or failure. If success, the Jenkinsfile contents will be in the jenkinsfile field. If failure, there'll be an additional array in the errors field of the error messages encountered.

    上述兩個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() 中不會存在silent

    silent = _{ ... }
    
  • 當使用原子語法時,整個規則體將視為一個規則,如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的功能。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM