Jenkins as code and go language learning

Source: Internet
Author: User
Tags sprintf webhook groovy script

Objective

Recently, the concept of Jenkins as code has been mentioned in many articles, and the eight principles of continuous delivery have all been put into version management, and we are recently ready to put some of our company's job configurations on Jenkins into git because https://github.com/ Jenkinsci/job-dsl-plugin's support is groovy. I didn't know groovy, so I looked for some online groovy scripts to change and implemented the template with go, and I practiced go.

All use to file introduction

A total of 3 files, only one template, if there are multiple scenarios can write more than a few templates

bogon:jenkins-dsl hongzhi.wang$ tree.├── config.yaml   #配置文件├── generate_dsl.go #go 源码文件└── springboot.tpl #go template 文件
Configuration file

This time the preparation of the template through the Yaml file rendering, configuration file as follows, through YAML to configure the file is clear.

- department_name: java  cn_name: java组  apps:    - app_name: app-1      nodes:        - node1        - node2        - node3      ansible_playbook_name: deploy-springboot-jar.yml      jvm_size: 2048m      template_name: springboot.tpl    - app_name: app-2      nodes:        - node1        - node2        - node3      ansible_playbook_name: deploy-springboot-jar.yml      jvm_size: 512m      template_name: springboot.tpl- department_name: java2  cn_name: java2组  apps:    - app_name: app-4      nodes:        - node1        - node2        - node3      ansible_playbook_name: deploy-springboot-war.yml      jvm_size: 2048m      template_name: springboot.tpl
GO Template

This is mainly used in the custom function, the ProcessNodes other is the normal use of the template, there is our Jenkins is the main parameter pull code, and then through the Ansible-playbook implementation of the application deployment.

def app_name = ' {{. App.appname}} ' def giturl = ' [email protected]:{{. Name}}/{{. App.appname}}.git "Job (" {{. Name}}-${app_name} ") {description () Keepdependencies (false) parameters {Choiceparam (" Mode ", [" Release "," Deploy "]," " ) Choiceparam ("App_name", ["${app_name}"], "") Choiceparam ("NODES", {{processnodes). App.nodes}}, "") Gitparam (' VERSION ') {sortmode (' descending ') tagfilter (' * ')}}scm {git {remote {URL (giturl) credentials ("Git")} Branch ("\ $VERSION")}}disabled (False) Concurrentbuild (false) steps {maven{configure {node->node/' Mavenname ' (' Maven ')}goals (' clean ')}maven{configure {node->node/' Mavenname ' (' maven ')}goals (' Install-pproduct ')}shell ("" " Source/opt/py3/bin/activateif [\ $Mode = = Release]thenstart_task= "Copy app code" fiecho \ $JOB _namecd/ansible/echo \ $WOR Kspacefor host in \ $NODESdoansible-playbook--start-at-task= "\ $START _task" {{. App.ansibleplaybookname}}--extra-vars "Target_host=\ $host workspace=\ $WORKSPACE app_name=\ $app _name version=\$ VERSION jvm_size={{ . App.jvmsize}} "Done" ")}}listview (" {{. Cnname}} ") {jobs {regex (/{{). Name}}-.+/)}columns {status () weather () name () lastsuccess () lastfailure () lastduration () Buildbutton ()}
Go source

This source code mainly according to the configuration file, the Department directory has been removed and the application groovy script is deleted, and pushed to the remote branch, groovy script name can not have - , because groovy's script name will be parsed into the Java class name, - Cannot be placed inside the class name of the Java language. So you can only turn the application name - into _ .

Package Mainimport ("Io/ioutil" "Github.com/ghodss/yaml" "FMT" "Text/template" "OS" "Log" "strings"     "Os/exec" "bytes") type Department struct {Name string ' JSON: ' Department_name ' ' Cnname string ' json: ' Cn_name ' Apps []app ' JSON: ' Apps ' '}type App struct {AppName string ' JSON: ' app_name ' ' Nodes []string ' JSON: ' Nodes ' ' Pyt Honversion string ' JSON: ' python_version ' ' jvmsize string ' json: ' jvm_size ' ' templatename string ' json: ' Template_name ' ' Ansibleplaybookname string ' json: ' Ansible_playbook_name ' ' DestPath string ' json: ' Dest_path ' ' Tomcatgiturl strin    G ' JSON: "Tomcat_git_url" ' Tomcatport string ' JSON: "Tomcat_port" ' Tomcatadminport string ' JSON: "Tomcat_admin_port" '     Tomcatname string ' JSON: ' Tomcat_name ' ' Tomcatwebapp string ' json: ' Tomcat_web_app ' '}func in (i string,l []string) bool{ For _, item:= range l{If item = = i{return True}} return False}func Checkerr (Err err OR) {if err! = nil{        Log. Fatal (Err)}}func processnodes (l []string) string {If Len (l) = = 1{return FMT. Sprintf (' ['%s '] ', strings. Join (L, ""))} return FMT. Sprintf (' ['%s ', '%s '] ', l[0],strings. Join (L, ""))}func Appnametofilename (appname String) string {appname = strings. Replace (appname, "-", "_", -1) return to FMT. Sprintf ("%s.groovy", appname)}func syscommand (command string) {commandlist: = strings. Fields (command) var out bytes.    Buffer cmd: = Exec.command (commandlist[0],commandlist[1:] ...) Cmd. Stdout = &out cmd. Stderr = &out Err: = cmd. Run () If err! = nil{log. Printf ("COMMD Error:%v", command)} log. Println (out). String ())}func main () {content,err: = Ioutil. ReadFile ("Config.yaml") Checkerr (ERR) var d []department err = Yaml. Unmarshal (content, &d) Checkerr (err) Departmentnames: = []string{} funcmap: = template. funcmap{"Processnodes": Processnodes,} for _, Department: = Range d{ERR: = OS. Mkdirall (Department. name,0755) Checkerr (err) departmentnames = append (departmentnames, department. Name) If appfilenames: = []string{}; Department. Apps! = nil{for _, App: = Range department. apps{FileName: = Appnametofilename (App.                    AppName) Appfilenames = append (appfilenames,filename) Data: = map[string]interface{}{ "Name":d epartment. Name, "Cnname":d epartment. Cnname, "app": App,} templ,err: = template. New (app. templatename). Funcs (Funcmap). Parsefiles (app. templatename) Checkerr (err) F, err: = OS. Create (FMT. Sprintf ("%s/%s", department. Name, FileName)) defer f.close () Checkerr (err) Err = Templ. Execute (f, data) Checkerr (ERR)} Existfiles,err: = Ioutil. ReadDir (department. Name) Checkerr (err) for _,v: = Range Existfiles{if! In (V.name (), appfilenames) {log. Println ("Going to delete file:", V.name ()) Syscommand (FMT. Sprintf ("Git rm%s/%s", department. Name,v.name ()))}}}} Existdirs,err: = Ioutil. ReadDir ("./") Checkerr (Err) for _,dir: = Range existdirs{if dir. Isdir () && dir. Name ()! = ". Idea" && dir. Name ()! = ". Git" &&! In (dir. Name (), departmentnames) {log. Println ("Going to delete dir:", dir.) Name ()) log. Printf ("Git rm-r%s\n", dir.) Name ()) Syscommand (FMT. Sprintf ("Git rm-r%s", dir.) Name ())) Checkerr (Err)}} syscommand ("Git add *") Syscommand ("Git commit-m ' update ')// Syscommand ("Git push") log. Println ("Finished")}

templ,err := template.New(app.TemplateName).Funcs(funcMap).ParseFiles(app.TemplateName)The reason for this is that to pass in a custom function, the return value of Parsefile is two that cannot be used directly with Funcs. This will be explained in the stack overflow answer.

Results of the script run
bogon:jenkins-dsl hongzhi.wang$ go run generate_dsl.go bogon:jenkins-dsl hongzhi.wang$ tree.├── config.yaml├── generate_dsl.go├── java│   ├── app_1.groovy│   └── app_2.groovy├── java2│   └── app_4.groovy└── springboot.tpl
The rest of the work

After the script pushes the code to Gitlab, Gitlab triggers a jenkins-seed-job through Webhook, and the job runs the groovy script, and the groovy script remembers to delete the existing one. We are a department corresponding to a jenkins-seed-job, a webhook. If the config.yaml is too big, you can put some department configuration into another source repository.

steps {        dsl {            ignoreExisting(false)            removeAction("DELETE")            removeViewAction("IGNORE")            lookupStrategy("JENKINS_ROOT")        }    }
Summarize

This time it was mostly about putting Jenkins's job management into version control and practicing go. Here is mainly to make a note o ( ̄︶ ̄) o.

Jenkins as code and go language learning

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.