Jenkins:批次自動將 Maven 型別 Job 遷移到自由風格型別

Tybyq發表於2019-11-12

為什麼要遷移?

近期進行 Jenkins 從1.X到2.X的升級演練
Jenkins2 最新版本只能在 JDK8 或 JDK11 版本下執行,我所使用的 JDK 版本為 JDK8
在構建 Maven Job,Job 配置的 JDK 版本為 JDK7時,構建報錯

$ /usr/local/java/bin/java -cp /data/jenkins/maven31-agent.jar:/usr/local/maven/boot/plexus-classworlds-2.5.2.jar:/usr/local/maven/conf/logging jenkins.maven3.agent.Maven31Main /usr/local/maven /data/jenkins/slave.jar /data/jenkins/maven31-interceptor.jar /data/jenkins/maven3-interceptor-commons.jar 45631Exception in thread "main" java.lang.UnsupportedClassVersionError: hudson/remoting/Launcher : Unsupported major.minor version 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:401)
        at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:271)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:247)
        at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:239)
        at jenkins.maven3.agent.Maven31Main.main(Maven31Main.java:138)
        at jenkins.maven3.agent.Maven31Main.main(Maven31Main.java:67)

經定位,原來 Maven 型別 Job 與 JDK 版本有一定相容性,部分說明如下:

Maven jobs and Java versions compatibility : Because java serialized classes are exchanged between Jenkins master and Maven Jobs it is required that the JVM used to launch Maven is superior or equal to the version of Java for which Jenkins Master is built for.

  • Jenkins >= 1.520 requires Java 6 thus Maven jobs must be launched with Java >= 6.

  • Jenkins >= 1.612 requires Java 7 thus Maven jobs must be launched with Java >= 7.

  • Jenkins >= 2.54 requires Java 8 thus Maven jobs must be launched with Java >= 8.

詳見:

而我們的這些 Job 必須使用指定 JDK 版本構建,不能隨意修改 JDK 版本
而自由風格型別的 Job,不會出現這個問題
所以,計劃將 Maven 型別 Job 遷移到自由風格型別

如何遷移?

那麼如何遷移呢?
統計了下 Maven 型別的 Job,有數百個,手動遷移不現實的
透過 google 發現有前人寫的 grovvy 指令碼:
嘗試執行該指令碼,可能與環境有關,它會報錯
由於對 groovy 不太熟悉,解決起來比較麻煩
所以參考它的邏輯,使用 python 指令碼實現了遷移的功能

python 指令碼如下所示,有需要的可以自行修改:

# -*- coding:utf-8 -*-import xml.etree.ElementTree as ETimport sysfrom jenkinsapi.jenkins import Jenkins
reload(sys)
sys.setdefaultencoding('utf8')def get_jenkins_server():
    JENKINS_URL = "
    JENKINS_USERNAME = "jenkins"
    JENKINS_PASSWORD = "jenkins"
    return Jenkins(JENKINS_URL, username=JENKINS_USERNAME, password=JENKINS_PASSWORD, timeout=30)def get_modified_xml(job_config_xml_tree):
    # create builders node
    builders_element = ET.Element("builders")
    job_config_xml_tree.append(builders_element)    # Move prebuilders to builders
    prebuilders_node = job_config_xml_tree.find("prebuilders")    if prebuilders_node is not None and prebuilders_node.getchildren() is not None:        for pre_builder in prebuilders_node.getchildren():
            builders_element.append(pre_builder)
    job_config_xml_tree.remove(prebuilders_node)    # Create a maven block
    maven_node = ET.Element("hudson.tasks.Maven")
    builders_element.append(maven_node)
    move(job_config_xml_tree.find("goals"), job_config_xml_tree, maven_node, "targets")
    maven_name_node = job_config_xml_tree.find("mavenName")    if maven_name_node:
        move(maven_name_node, job_config_xml_tree, maven_node)    else:
        maven_name_node = ET.Element("mavenName")
        maven_name_node.text = "Maven"
        maven_node.append(maven_name_node)
    move(job_config_xml_tree.find("rootPOM"), job_config_xml_tree, maven_node)
    move(job_config_xml_tree.find("mavenOpts"), job_config_xml_tree, maven_node)
    move(job_config_xml_tree.find("settings"), job_config_xml_tree, maven_node)
    move(job_config_xml_tree.find("globalSettings"), job_config_xml_tree, maven_node)    # items that don't exist in maven step:
    remove(job_config_xml_tree, [        'resolveDependencies',        'processPlugins',        'siteArchivingDisabled',        'archivingDisabled',        'mavenValidationLevel',        'disableTriggerDownstreamProjects',        'blockTriggerWhenBuilding',        'fingerprintingDisabled',        'incrementalBuild',        'processPlugins',        'siteArchivingDisabled',        'ignoreUpstremChanges',        'rootModule'
    ])    # Move postbuilders to builders
    postbuilders_node = job_config_xml_tree.find("postbuilders")    if postbuilders_node is not None and postbuilders_node.getchildren() is not None:        for post_builder in postbuilders_node.getchildren():
            builders_element.append(post_builder)
    job_config_xml_tree.remove(postbuilders_node)    # rename top-level element
    # new parent node
    new_job_config_xml_tree = ET.Element("project")    for child_node in job_config_xml_tree.getchildren():
        new_job_config_xml_tree.append(child_node)    return new_job_config_xml_treedef move(from_node, from_parent_node, to_node, to_name=None):
    if from_node is not None:        if to_name:
            tmp_element_node = ET.Element(to_name)
            tmp_element_node.text = from_node.text
            tmp_element_node.attrib = from_node.attrib
            to_node.append(tmp_element_node)
            from_parent_node.remove(from_node)        else:
            to_node.append(from_node)
            from_parent_node.remove(from_node)def remove(from_node, name_list):
    for name in name_list:
        tmp_node = from_node.find(name)        if tmp_node is not None:
            from_node.remove(tmp_node)def main():
    jenkins_server = get_jenkins_server()
    job_list = jenkins_server.get_jobs_list()    for job_name in job_list:        if not job_name.endswith("-DEPRECATED"):
            job_obj = jenkins_server.get_job(job_name)
            config_text = job_obj.get_config()
            config_xml_tree = ET.fromstring(config_text)            if config_xml_tree.tag == "maven2-moduleset":
                new_config_xml_tree = get_modified_xml(config_xml_tree)
                new_config_xml = ET.tostring(new_config_xml_tree)
                jenkins_server.rename_job(job_name, job_name + "-DEPRECATED")
                jenkins_server.create_job(job_name, new_config_xml)
                print("migrate job from Maven Type to FreeStyle Type: " + job_name)if __name__ == "__main__":
    main()


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557424/viewspace-2663750/,如需轉載,請註明出處,否則將追究法律責任。

相關文章