文章導讀
- 本文僅代表作者的個人觀點;
- 本文的內容僅限於技術探討,不能作爲指導生產環境的素材;
- 本文素材是紅帽公司產品技術和手冊;
一、實現Devops的金箍
容器在工具層面實現Devops。
這句話不是我說的,Gartner說的。
但說出這句話,和實現Devops全工具鏈落地之間的差距,與造出原子彈和E=MC2公式的差距,實不逞多讓。
那麼,從容器到Devops工具鏈,都需要啥呢?
之前我的一遍文章已經提到過,至少需要六大金剛。
Openshift:PaaS解決方案
Gogs: Go寫的本地github
Jenkins/Jenkins Slave Pods
Nexus :工件管理器,能夠解決本地緩存構建依賴項。
SonarQube:開源代碼分析工具,它可以分析常見編程錯誤的源代碼
Skopeo:鏡像複製工具
理論上,七個葫蘆一顆心,才能打敗妖精。
同樣,六大金剛協同工作,才能實現Devops。
那麼,將這六大金剛協調起來,打通devops任督二脈的金箍圈是啥?
一個完整、全面的Jenkins Pipeline。
任何沒有試驗和代碼的技術文章都是耍流氓,閒言少敘,看乾貨!
二、實驗環境介紹
我的試驗環境集成了六大金剛,五個工具分別在不同的Openshift項目中(Skopeo被做到了Jenkins Slave pod image中):
試驗最最終實現效果:
- 構建了一個pipeline,將openshift-tasks應用程序交付到生產環境中。
- 構建過程集成了Gogs、Nexus、SonarQube和S2I構建。
- 最終部署到生產中使用藍綠色部署。
- 將新版本的應用程序推送到Gogs時,可以配置要觸發的pipeline。
- 將pipeline與OpenShift Web控制檯集成。
最終Pipeline的全流程:
- 設置OpenShift開發(包括測試)和生產項目
- 在Jenkins建立一個pipeline
- 查看Gogs的源代碼
- 使用Nexus作爲Maven代理從源代碼構建應用程序
- 將標記x.x-Buildnumber添加到構建的image
- 運行單元測試
- 運行代碼覆蓋測試
- 將x.x標記添加到image
- 將容器image保存到Nexus Docker註冊表
- 使用藍綠部署將應用程序部署到生產環境
- 停止pileline,等待批准
- 批准後,將路由切換到新部署
展示效果:
應用在向生產環境部署之前,詢問是否批准:
如果同意切換到生產:
則應用部署到生產:
而最終部署的應用的web展示:
六大金剛協同工作圖:
在比較簡單的模式下:開發人員將代碼push到git(gogs)中,Jenkins觸發Tasks-Dev中的dc,觸發構建,構建成功後,將構建好image推送到docker registry中。然後,鏡像在Tasks-Dev中通過dc進行部署,然後給新的鏡像打label,最後將鏡像部署到Tasks-Prod中:
在本實驗中,開發人員將代碼推送到git中,Jenkins Pipeline啓動Jenkins Slave Pod,進行構建(構建成war包),然後war包被推到SonarQube中進行代碼分析,分析通過以後,war包被推送到Nexus中:
三、環境準備:創建dev和prod兩個項目
我們在OpenShift中,針對一個應用tasks,創建dev和prod兩個項目,模擬開發和生產。
創建xyz-tasks-dev80 OpenShift項目來保存openshift-tasks應用程序的開發版本:
- 設置Jenkins的權限,以便能夠操作xyz-tasks-dev項目中的對象。
- 使用jboss-eap70-openshift:1.6 image stream創建二進制構建。
- 創建指向任務的新部署配置:0.0-0。
- 關閉自動構建和部署。
- 將部署配置公開爲服務(在端口8080上),爲service 配置route。
- 將ConfigMap附加到dc。
下面是操作命令截圖,不再一 一解釋:
創建生產項目,命令行如下,具體截圖不再展示:
oc new-project xyz-tasks-prod80 --display-name "Tasks Production80"
oc policy add-role-to-group system:image-puller system:serviceaccounts:xyz-tasks-prod80 -n xyz-tasks-dev80
oc policy add-role-to-user edit system:serviceaccount:xyz-jenkins:jenkins -n xyz-tasks-prod80
常見的兩個項目如下:
四、環境準備:創建藍綠應用
創建Blue應用:
oc new-app xyz-tasks-dev80/tasks:0.0 --name=tasks-blue --allow-missing-imagestream-tags=true -n xyz-tasks-prod80
oc set triggers dc/tasks-blue --remove-all -n xyz-tasks-prod80
oc expose dc tasks-blue --port 8080 -n xyz-tasks-prod80
oc create configmap tasks-blue-config --from-literal="application-users.properties=Placeholder" --from-literal="application-roles.properties=Placeholder" -n xyz-tasks-prod80
oc set volume dc/tasks-blue --add --name=jboss-config --mount-path=/opt/eap/standalone/configuration/application-users.properties --sub-path=application-users.properties --configmap-name=tasks-blue-config -n xyz-tasks-prod80
oc set volume dc/tasks-blue --add --name=jboss-config1 --mount-path=/opt/eap/standalone/configuration/application-roles.properties --sub-path=application-roles.properties --configmap-name=tasks-blue-config -n xyz-tasks-prod80
創建Green應用:
oc new-app xyz-tasks-dev80/tasks:0.0 --name=tasks-green --allow-missing-imagestream-tags=true -n xyz-tasks-prod80
oc set triggers dc/tasks-green --remove-all -n xyz-tasks-prod80
oc expose dc tasks-green --port 8080 -n xyz-tasks-prod
oc create configmap tasks-green-config --from-literal="application-users.properties=Placeholder" --from-literal="application-roles.properties=Placeholder" -n xyz-tasks-prod80
oc set volume dc/tasks-green --add --name=jboss-config --mount-path=/opt/eap/standalone/configuration/application-users.properties --sub-path=application-users.properties --configmap-name=tasks-green-config -n xyz-tasks-prod80
oc set volume dc/tasks-green --add --name=jboss-config1 --mount-path=/opt/eap/standalone/configuration/application-roles.properties --sub-path=application-roles.properties --configmap-name=tasks-green-config -n xyz-tasks-prod80
創建路由,並將路由指向到藍應用:
oc expose svc/tasks-blue --name tasks -n xyz-tasks-prod80
(在Pipeline第一次跑通以後,發佈的應用指向了Green應用。爲何?因爲在Pipeline中,第十步會進行藍綠切換,這點其實也好理解:生產上通常不會部署最新版本的應用,dev環境開發新版本,prod部署上一個版本)
四、Pileline的十二個階段
在正式書寫Pileline之前,我們先將框架寫出來。
這個Pipeline包含以下十二個步驟
步驟1 :代碼遷出
// Checkout Source Code
stage('Checkout Source') {
// TBD
}
設置代碼版本號:
// Set the tag for the development image: version + build number
def devTag = "0.0-0"
// Set the tag for the production image: version
def prodTag = "0.0"
步驟2:構建war包
stage('Build war') {
echo "Building version ${version}"
// TBD
}
步驟3:單元測試
// Using Maven run the unit tests
stage('Unit Tests') {
echo "Running Unit Tests"
// TBD
}
步驟4 :代碼分析
// Using Maven call SonarQube for Code Analysis
stage('Code Analysis') {
echo "Running Code Analysis"
// TBD
}
步驟5:將war推送到Nexus
// Publish the built war file to Nexus
stage('Publish to Nexus') {
echo "Publish to Nexus"
// TBD
}
步驟6:Openshift中構建docker image
// Build the OpenShift Image in OpenShift and tag it.
stage('Build and Tag OpenShift Image') {
echo "Building OpenShift container image tasks:${devTag}"
// TBD
}
步驟7:在dev項目中部署鏡像
// Deploy the built image to the Development Environment.
stage('Deploy to Dev') {
echo "Deploying container image to Development Project"
// TBD
}
步驟8:進行集成測試
// Run Integration Tests in the Development Environment.
stage('Integration Tests') {
echo "Running Integration Tests"
// TBD
}
步驟9:將鏡像拷貝到Nexus Docker Registry
// Copy Image to Nexus Docker Registry
stage('Copy Image to Nexus Docker Registry') {
echo "Copy image to Nexus Docker Registry"
// TBD
}
步驟10:在prod項目中進行藍綠部署
// Blue/Green Deployment into Production
// -------------------------------------
// Do not activate the new version yet.
def destApp = "tasks-green"
def activeApp = ""
stage('Blue/Green Production Deployment') {
// TBD
}
步驟11 :切換應用版本到生產
stage('Switch over to new Version') {
// TBD
echo "Switching Production application to ${destApp}."
// TBD
}
}
步驟12 :代碼遷出
// Checkout Source Code
stage('Checkout Source Code') {
checkout scm
}
}
五、Pileline的第一個階段:獲取源代碼
Pilpeline的第一步是從Gogs中的openshift-tasks-private存儲庫獲取源代碼。
- 我們需要考慮的點有:
- 源代碼庫的URL是什麼?
- 如何訪問Gogs嗎?
- 如何指定Jenkins的身份驗證憑據,以訪問Gogs?
首先,我們在Jenkins上生成一個credentialsId(就是相當於在Jenkins上對Gogs的用戶名和密碼做加密處理,避免寫Pileline的時候出現明文)
需要注意的是,下面輸入的用戶名和密碼是gogs的,創建成功以後,會隨機創建一個 credentialsId.
然後,使用獲取到的 credentialsId,書寫Pipeline的第一個階段,從gogs的私有倉庫中獲取源代碼。
在下面的內容中,node後面的內容,表示構建的時候,使用的maven slave pod的鏡像,尋找的時候,是通過maven-appdev 這個label來匹配的:
#!groovy
// Run this pipeline on the custom Maven Slave ('maven-appdev')
// Maven Slaves have JDK and Maven already installed
// 'maven-appdev' has skopeo installed as well.
node('maven-appdev') {
// Define Maven Command. Make sure it points to the correct
// settings for our Nexus installation (use the service to
// bypass the router). The file nexus_openshift_settings.xml
// needs to be in the Source Code repository.
def mvnCmd = "mvn -s ./nexus_openshift_settings.xml"
stage('David Checkout Source') {
git credentialsId: '5e38511b-5ded-41b7-a385-36fd9bab279f', url: 'http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git'
}
源代碼Checkout後,pipeline可以檢查pom.xml文件(該文件位於gogs的私有倉庫中),以確定要構建的應用程序的版本。 最佳做法是將開發標記設置爲版本號,加上Jenkins的實際內部版本號的組合。 這樣,每次版本號不同時,我們可以多次運行Pileline。 當構建通過所有檢查並將image標記爲準備生產時,標記只是版本號。
在pipeline中,在以下部分中設置正確的tag:
def devTag = "${version}-${BUILD_NUMBER}"
def prodTag = "${version}"
六、Pileline的第二個階段:構建war
pipeline中的第二步是從源代碼構建WAR文件,我們需要考慮:
- pipeline將環境變量mvnCmd定義爲mvn -s ./nexus_openshift_settings.xml。
- nexus_openshift_settings.xml位於Gogs存儲庫中,需要指向正確的Nexus服務。
本步驟中,使用-DskipTests繞過單元測試(下一個階段運行)
首先修改源碼庫中的nexus_openshift_settings.xml和nexus_openshift_settings.xml配置:
然後,書寫Pileline:
// Using Maven build the war file
// Do not run tests in this step
stage('David Build war') {
echo "Building version ${devTag}"
sh "${mvnCmd} clean package -DskipTests"
}
七、Pileline的第三個階段:運行單元測試
構建WAR文件後,運行單元測試。運行Pileline並驗證單元測試是否成功完成。
// Using Maven run the unit tests
stage('David Unit Tests') {
echo "Running Unit Tests"
sh "${mvnCmd} test"
}
八、Pileline的第四個階段:運行代碼分析
在本階段中,使用SonarQube運行代碼覆蓋率測試
我們需要考慮以下內容:
- 運行SonarQube分析的Maven命令
- SonarQube服務的URL
- SonarQube的項目名稱
stage('David Code Analysis') {
echo "David Running Code Analysis"
sh "${mvnCmd} sonar:sonar -Dsonar.host.url=http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/ -Dsonar.projectName=${JOB_BASE_NAME}-${devTag}"
}
九、Pileline的第五個階段:將代碼測試通過的WAR文件存儲在Nexus
一旦代碼覆蓋率測試成功,我們將war push到Nexus中:
stage('David Publish war to Nexus') {
echo "Publish to Nexus"
sh "${mvnCmd} deploy -DskipTests=true -DaltDeploymentRepository=nexus::default::http://nexus3.xyz-nexus80.svc.cluster.local:8081/repository/releases"
}
十、Pileline的第六個階段:在OpenShift中構建docker image
歸檔WAR文件後,接下來,在OpenShift中構建容器映像。 在這個過程中,我們使用B2I。
下面做的操作,是將Jenkis workspace目錄中的./target/openshift-tasks.war文件,寶貝到tasks:1.1-10中。而builder image的定義,卸載了tasks的bc中:
// Build the OpenShift Image in OpenShift and tag it.
stage('David Build and Tag OpenShift Image') {
echo "Building OpenShift container image tasks:${devTag}"
sh "oc start-build tasks --follow --from-file=./target/openshift-tasks.war -n xyz-tasks-dev80"
openshiftTag alias: 'false', destStream: 'tasks', destTag: devTag, destinationNamespace: 'xyz-tasks-dev80', namespace: 'xyz-tasks-dev80', srcStream: 'tasks', srcTag: 'latest', verbose: 'false'
}
十一、Pileline的第七個階段:將構建的映像部署到開發項目中
接下來是部署剛剛構建的容器映像。 xyz-tasks-dev80項目中已經有任務部署配置。它指向如下版本task應用:0.0-0 image。
該項目還包含一個tasks-config ConfigMap,它應該包含兩個JBoss EAP映像的配置文件。在常規S2I構建中,源代碼存儲庫中配置目錄中的所有內容都會自動複製到構建映像中的JBoss EAP配置中。但是,因爲我們使用二進制構建來構建映像,所以不會發生這種情況。因此,需要使用ConfigMap將配置文件添加到部署配置中。
我們需要刪除當前的ConfigMap並使用兩個文件./configuration/application-users.properties和./configuration/application-roles.properties創建一個新文件。
創建ConfigMap後,使用更新的映像和ConfigMap部署應用程序,然後驗證部署是否成功。
// Deploy the built image to the Development Environment.
stage('David Deploy app to Dev') {
echo "Deploying container image to Development Project"
sh "oc set image dc/tasks tasks=docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:${devTag} -n xyz-tasks-dev80"
sh "oc delete configmap tasks-config -n xyz-tasks-dev80 --ignore-not-found=true"
sh "oc create configmap tasks-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-dev80"
openshiftDeploy depCfg: 'tasks', namespace: 'xyz-tasks-dev80', verbose: 'false', waitTime: '', waitUnit: 'sec'
openshiftVerifyDeployment depCfg: 'tasks', namespace: 'xyz-tasks-dev', replicaCount: '1', verbose: 'false', verifyReplicaCount: 'false', waitTime: '', waitUnit: 'sec'
openshiftVerifyService namespace: 'xyz-tasks-dev80', svcName: 'tasks', verbose: 'false'
}
十二、Pileline的第八個階段:運行集成測試
本階段運行集成測試。
openshift-tasks應用程序是一個簡單的任務管理應用程序,具有用於創建,檢索和刪除任務的REST接口。 應用程序的README文件包含有關用戶ID和操作任務的可能命令的信息。
在此pileline中,我們創建一個任務、通過http方法檢測API,然後刪除該任務。
// Run Integration Tests in the Development Environment.
stage('David Run Integration Tests') {
echo "Running Integration Tests"
sleep 15
// Create a new task called "integration_test_1"
echo "Creating task"
sh "curl -i -u 'tasks:redhat1' -H 'Content-Length: 0' -X POST http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/integration_test_1"
// Retrieve task with id "1"
echo "Retrieving tasks"
sh "curl -i -u 'tasks:redhat1' -H 'Content-Length: 0' -X GET http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1"
// Delete task with id "1"
echo "Deleting tasks"
sh "curl -i -u 'tasks:redhat1' -H 'Content-Length: 0' -X DELETE http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1"
十三、Pileline的第九個階段:將docker image複製到Nexus Container Registry
在大多數客戶的環境中,非生產和生產需要做物理隔離。因此pipeline需要將測試的容器映像移動到另一個容器註冊表、或另一個OpenShift集羣。
在我的韓靜中,Nexus配置爲充當Docker registry。 使用skopeo將test image從集成的OpenShift Container Registry複製到Nexus的Container Registry。 將image複製到Nexus後,需要將image標記爲已準備推動到生產環境。
// Copy Image to Nexus Docker Registry
stage('David Copy Image to Nexus Docker Registry') {
echo "Copy image to Nexus Docker Registry"
sh "skopeo copy --src-tls-verify=false --dest-tls-verify=false --src-creds openshift:\$(oc whoami -t) --dest-creds admin:admin123 docker://docker-registry.default.svc.cluster.local:5000/xyz-tasks-dev80/tasks:${devTag} docker://nexus-registry.xyz-nexus80.svc.cluster.local:5000/tasks:${devTag}"
// Tag the built image with the production tag.
// Replace xyz-tasks-dev with the name of your dev project
openshiftTag alias: 'false', destStream: 'tasks', destTag: prodTag, destinationNamespace: 'xyz-tasks-dev80', namespace: 'xyz-tasks-dev80', srcStream: 'tasks', srcTag: devTag, verbose: 'false'
}
}
十四、Pileline的第十個階段:使用藍綠部署部署將應用發佈到生產
將容器映像安全地存儲在Nexus Container registry中後,即可將映像部署到生產環境中。
由於image位於OpenShift外部的Container registry中,因此我們可以將image部署到完全不同的集羣中進行生產。在這種情況下,需要啓用羣集以從此外部註冊表中提取 - 或者再次使用skopeo將映像複製到生產羣集中的容器註冊表。
使用藍綠色部署方法來執行部署。這意味着:
- 需要確定當前活動的應用程序版本(藍色或綠色)。
- 需要使用JBoss EAP服務器配置更新正確的ConfigMap。
- 將新應用程序部署到當前不活動的應用程序。
在此pipeline中,在切換路由之前,需要在部署新版本的應用程序時停止批准。
// Blue/Green Deployment into Production
// -------------------------------------
// Do not activate the new version yet.
def destApp = "tasks-green"
def activeApp = ""
stage('Blue/Green Production Deployment') {
activeApp = sh(returnStdout: true, script: "oc get route tasks -n xyz-tasks-prod80 -o jsonpath='{ .spec.to.name }'").trim()
if (activeApp == "tasks-green") {
destApp = "tasks-blue"
}
echo "Active Application: " + activeApp
echo "Destination Application: " + destApp
// Update the Image on the Production Deployment Config
sh "oc set image dc/${destApp} ${destApp}=docker-registry.default.svc:5000/xyz-tasks-dev8080/tasks:${prodTag} -n xyz-tasks-prod80"
// Update the Config Map which contains the users for the Tasks application
sh "oc delete configmap ${destApp}-config -n xyz-tasks-prod80 --ignore-not-found=true"
sh "oc create configmap ${destApp}-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-prod80"
// Deploy the inactive application.
// Replace xyz-tasks-prod with the name of your production project
openshiftDeploy depCfg: destApp, namespace: 'xyz-tasks-prod80', verbose: 'false', waitTime: '', waitUnit: 'sec'
openshiftVerifyDeployment depCfg: destApp, namespace: 'xyz-tasks-prod80', replicaCount: '1', verbose: 'false', verifyReplicaCount: 'true', waitTime: '', waitUnit: 'sec'
openshiftVerifyService namespace: 'xyz-tasks-prod80', svcName: destApp, verbose: 'false'
}
十四、Pileline的第十一個階段:到生產藍綠切換
本階段,應用程序現在可以進行切換。 應用程序已完全運行並準備接收流量。 如果需要,可以在切換流量之前使用生產環境(羣集)中的實時應用程序運行另一個測試。 在我的實驗中,增加了審批流程, 一旦批准,pipeline就會將路徑從舊應用程序切換到新應用程序。
stage('David do Switch over to new Version') {
input "Switch Production?"
echo "Switching Production application to ${destApp}."
sh 'oc patch route tasks -n xyz-tasks-prod80 -p \'{"spec":{"to":{"name":"' + destApp + '"}}}\''
}
十五、Pileline的第十二個階段:代碼checkout
// Checkout Source Code
stage('David Checkout Source') {
checkout scm
}
接下來,截至到目前,主的Jenkins file已經寫完。我們將這個Jenkins file上傳到Gogs的代碼倉庫中,和源碼放在一起:
十六、設置web hook
我們要實現:開發人員將新代碼推送到openshift-tasks-private1存儲庫時,自動觸發構建,需要Gogs中設置Git掛鉤。
在Jenkins中找到授權令牌,打開瀏覽器並登錄Jenkins,在右上角,單擊用戶名旁邊的向下箭頭,然後選擇配置。
單擊“顯示API令牌”並記下顯示的用戶ID和API令牌。
接下來,在Gogs中創建Web掛鉤:
打開瀏覽器,導航到Gogs服務器,登錄,然後轉到CICDLabs / openshift-tasks-private1存儲庫,單擊“設置”,然後單擊“Git Hooks”。
配置Git鉤子:
將此腳本複製並粘貼到Hook Content字段中,將<userid>和<apiToken>替換爲Jenkins用戶ID和API令牌,將<jenkinsService>替換爲Jenkins服務的名稱,將<jenkinsProject>替換爲OpenShift項目的名稱您的Jenkins服務位於:
十七、觸發構建測試
提交新版本的應用程序源代碼,會觸發新的構建。 每次更改應用程序時,最好增加版本號。 我們可以手動或自動遞增版本號。
我們進行測試:
export VERSION=1.1
mvn versions:set -f pom.xml -s nexus_settings.xml -DgenerateBackupPoms=false -DnewVersion=${VERSION}
git add pom.xml src/main/webapp/index.jsp
git commit -m "Increased version to ${VERSION}"
git push private master
驗證此推送是否觸發了Jenkins中的新構建。
確保pipeline各個階段都能成功:
十八:使用pipeline構建配置
通過上面的步驟,我們寫好了一個Jenkins File,可以在Jenkins觸發構建。
但爲了方便統一管理,我們可以使用Pipeline構建策略創建OpenShift構建配置,而不是在Jenkins中定義pileline。說簡單點,就是在Openshift中寫一個Pipeline/BC,觸發上面寫的Jenkins File( 此bc必須與Jenkins pod位於同一項目中除非將master-config.yaml配置爲指向另一個Jenkins實例)。
創建tasks-pipeline.yaml文件:
echo "apiVersion: v1
items:
- kind: "BuildConfig"
apiVersion: "v1"
metadata:
name: "tasks-pipeline"
spec:
source:
type: "Git"
git:
uri: "http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1"
strategy:
type: "JenkinsPipeline"
jenkinsPipelineStrategy:
jenkinsfilePath: Jenkinsfile
kind: List
metadata: []" | oc create -f - -n xyz-jenkins80
創建secret並與bc相關聯:
oc secrets new-basicauth gogs-secret --username=david --password=david -n xyz-jenkins80
oc set build-secret --source bc/tasks-pipeline gogs-secret -n xyz-jenkins80
在OpenShift Web控制檯中,切換到Jenkins項目並導航到Builds→Pipelines。
單擊“Start Pipeline”以觸發Pipeline:
單擊“查看日誌”以查看pipeline進度並在Jenkins中進行操作。
最後,我將整個Pipeline的日誌的重要部分提出來,以便參考(註解是我加上的,並非在原始的log中):
OpenShift Build xyz-jenkins80/tasks-pipeline-10 from http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 //從Gogs獲取Jenkins file,然後開始執行Jenkins File:Checking out git http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 into /var/lib/jenkins/jobs/xyz-jenkins80/jobs/xyz-jenkins80-tasks-pipeline/workspace@script to read Jenkinsfile > git rev-parse --is-inside-work-tree # timeout=10 Fetching changes from the remote Git repository > git config remote.origin.url http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 # timeout=10 Fetching upstream changes from http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 > git --version # timeout=10 using GIT_ASKPASS to set credentials xyz-jenkins80-gogs-secret > git fetch --tags --progress http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 +refs/heads/*:refs/remotes/origin/* > git rev-parse origin/master^{commit} # timeout=10 Checking out Revision 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 (origin/master) > git config core.sparsecheckout # timeout=10 > git checkout -f 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 Commit message: "更新 'Jenkinsfile'" > git rev-list --no-walk 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 # timeout=10 [Pipeline] node Still waiting to schedule task maven-appdev-wt2zs is offline //此時啓動Jenkins Slave Pod: Running on maven-appdev-wt2zs in /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline [Pipeline] { [Pipeline] stage //此時開始遷出源代碼[Pipeline] { (David Checkout Source)[Pipeline] git Cloning the remote Git repository Cloning repository http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git > git init /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline # timeout=10 Fetching upstream changes from http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git > git --version # timeout=10 using GIT_ASKPASS to set credentials gogsname > git fetch --tags --progress http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git +refs/heads/*:refs/remotes/origin/* > git config remote.origin.url http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git # timeout=10 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git # timeout=10 Fetching upstream changes from http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git using GIT_ASKPASS to set credentials gogsname > git fetch --tags --progress http://gogs.xyz-gogs80.svc.cluster.local:3000/CICDLabs/openshift-tasks-private1.git +refs/heads/*:refs/remotes/origin/* > git rev-parse refs/remotes/origin/master^{commit} # timeout=10 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10 Checking out Revision 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 (refs/remotes/origin/master) > git config core.sparsecheckout # timeout=10 > git checkout -f 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 > git branch -a -v --no-abbrev # timeout=10 > git checkout -b master 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 Commit message: "更新 'Jenkinsfile'" > git rev-list --no-walk 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 # timeout=10 [Pipeline] } [Pipeline] // stage [Pipeline] readFile [Pipeline] readFile [Pipeline] readFile //此時開始構建war包[Pipeline] stage[Pipeline] { (David Build war)[Pipeline] echo Building version 1.1-10 [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script+ mvn -s ./nexus_openshift_settings.xml clean package -DskipTestsPicked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true [INFO] Scanning for projects... Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jboss/bom/eap/jboss-javaee-6.0-with-tools/6.4.0.GA/jboss-javaee-6.0-with-tools-6.4.0.GA.pom 4/8 KB 8/8 KB
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jboss/jboss-parent/9/jboss-parent-9.pom (28 KB at 299.8 KB/sec) [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building JBoss EAP - Tasks App 1.1 [INFO] ------------------------------------------------------------------------ Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jacoco/jacoco-maven-plugin/0.7.9/jacoco-maven-plugin-0.7.9.pom 4/5 KB 5/5 KB Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public
68/168 KB 38/38 KB Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-shared-utils/0.9/maven-shared-utils-0.9.jar (168 KB at 1552.3 KB/sec) Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/surefire/surefire-grouper/2.19.1/surefire-grouper-2.19.1.jar (38 KB at 302.2 KB/sec) ------------------------------------------------------- T E S T S ------------------------------------------------------- Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true Running org.jboss.as.quickstarts.tasksrs.service.TaskResourceTest Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.51 sec - in org.jboss.as.quickstarts.tasksrs.service.TaskResourceTest Running org.jboss.as.quickstarts.tasksrs.service.UserResourceTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.001 sec - in org.jboss.as.quickstarts.tasksrs.service.UserResourceTest Results : Tests run: 4, Failures: 0, Errors: 0, Skipped: 1 //war包構建成功[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 44.914 s [INFO] Finished at: 2018-08-31T06:36:00+00:00 [INFO] Final Memory: 16M/178M [INFO] ------------------------------------------------------------------------ [Pipeline] } [Pipeline] // stage [Pipeline] stage //開始做代碼分析[Pipeline] { (David Code Analysis) [Pipeline] echo David Running Code Analysis [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + mvn -s ./nexus_openshift_settings.xml sonar:sonar -Dsonar.host.url=http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/ -Dsonar.projectName=xyz-jenkins80-tasks-pipeline-1.1-10 Picked up JAVA_TOOL_OPTIONS: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true [INFO] Scanning for projects... Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/jboss/as/plugins/jboss-as-maven-plugin/7.4.Final/jboss-as-maven-plugin-7.4.Final.pom 4/13 KB 8/13 KB 12/13 KB
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/sonarsource/scanner/maven/sonar-maven-plugin/3.3.0.603/sonar-maven-plugin-3.3.0.603.jar (54 KB at 266.7 KB/sec) [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building JBoss EAP - Tasks App 1.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- sonar-maven-plugin:3.3.0.603:sonar (default-cli) @ tasks --- Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-dependency-tree/2.2/maven-dependency-tree-2.2.pom 4/8 KB 8/8 KB Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-dependency-tree/2.2/maven-dependency-tree-2.2.pom (8 KB at 35.5 KB/sec) Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-shared-components/20/maven-shared-components-20.pom 4/5 KB 5/5 KB Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/apache/maven/shared/maven-shared-components/20/maven-shared-components-20.pom (5 KB at 25.6 KB/sec) Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/eclipse/aether/aether-util/0.9.0.M2/aether-util-0.9.0.M2.pom 2/2 KB Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/eclipse/aether/aether-util/0.9.0.M2/aether-util-0.9.0.M2.pom (2 KB at 18.9 KB/sec) Downloading: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/eclipse/aether/aether/0.9.0.M2/aether-0.9.0.M2.pom 4/28 KB 8/28 KB 12/28 KB 16/28 KB 20/28 KB 24/28 KB
Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/commons-lang/commons-lang/2.6/commons-lang-2.6.jar (278 KB at 447.7 KB/sec) Downloaded: http://nexus3-xyz-nexus80.apps.0845.openshift.opentlc.com/repository/maven-all-public/org/sonarsource/scanner/api/sonar-scanner-api/2.9.0.887/sonar-scanner-api-2.9.0.887.jar (520 KB at 744.4 KB/sec) [INFO] User cache: /home/jenkins/.sonar/cache [INFO] Publish mode [INFO] Load global settings [INFO] Load global settings (done) | time=223ms [INFO] Server id: AWV_FuWdgycr44kTc7kD [INFO] User cache: /home/jenkins/.sonar/cache [INFO] Load plugins index [INFO] Load plugins index (done) | time=55ms [INFO] Download sonar-flex-plugin-2.3.jar [INFO] Download sonar-csharp-plugin-6.5.0.3766.jar [INFO] Download sonar-javascript-plugin-3.2.0.5506.jar [INFO] Download sonar-java-plugin-4.15.0.12310.jar [INFO] Download sonar-php-plugin-2.11.0.2485.jar [INFO] Download sonar-python-plugin-1.8.0.1496.jar [INFO] Download sonar-scm-git-plugin-1.3.0.869.jar [INFO] Download sonar-scm-svn-plugin-1.6.0.860.jar [INFO] Download sonar-typescript-plugin-1.1.0.1079.jar [INFO] Download sonar-xml-plugin-1.4.3.1027.jar [INFO] SonarQube version: 6.7.4 [INFO] Default locale: "en_US", source code encoding: "UTF-8" [INFO] Process project properties [INFO] Load project repositories [INFO] Load project repositories (done) | time=207ms [INFO] Load quality profiles [INFO] Load quality profiles (done) | time=92ms [INFO] Load active rules [INFO] Load active rules (done) | time=704ms [INFO] Load metrics repository [INFO] Load metrics repository (done) | time=96ms [INFO] Project key: org.jboss.quickstarts.eap:tasks[INFO] ------------- Scan xyz-jenkins80-tasks-pipeline-1.1-10[INFO] Load server rules [INFO] Load server rules (done) | time=74ms [INFO] Base dir: /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline [INFO] Working dir: /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/target/sonar [INFO] Source paths: src/main/webapp, pom.xml, src/main/java [INFO] Test paths: src/test/java [INFO] Source encoding: UTF-8, default locale: en_US [INFO] Index files [INFO] 123 files indexed [INFO] Quality profile for java: Sonar way [INFO] Quality profile for js: Sonar way [INFO] Quality profile for xml: Sonar way [INFO] Sensor JavaSquidSensor [java] [INFO] Configured Java source version (sonar.java.source): 8 [INFO] JavaClasspath initialization [INFO] JavaClasspath initialization (done) | time=89ms [INFO] JavaTestClasspath initialization [INFO] JavaTestClasspath initialization (done) | time=1ms [INFO] Java Main Files AST scan [INFO] 11 source files to be analyzed [INFO] 6/11 files analyzed, current file: /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/src/main/java/org/jboss/as/quickstarts/tasksrs/model/User.java [INFO] Java Main Files AST scan (done) | time=16992ms [INFO] 11/11 source files have been analyzed [INFO] Java Test Files AST scan [INFO] 7 source files to be analyzed [INFO] Java Test Files AST scan (done) | time=6396ms [INFO] Sensor JavaSquidSensor [java] (done) | time=28197ms [INFO] Sensor SurefireSensor [java] [INFO] Property 'sonar.junit.reportsPath' is deprecated. Use property 'sonar.junit.reportPaths' instead. [INFO] parsing [/tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/target/surefire-reports] [INFO] 7/7 source files have been analyzed [INFO] Sensor SurefireSensor [java] (done) | time=1901ms [INFO] Sensor JaCoCoSensor [java] [INFO] Analysing /tmp/workspace/xyz-jenkins80/xyz-jenkins80-tasks-pipeline/target/jacoco.exec [INFO] No information about coverage per test. [INFO] Sensor JaCoCoSensor [java] (done) | time=1002ms [INFO] Sensor SonarJavaXmlFileSensor [java] [INFO] 4 source files to be analyzed [INFO] Sensor SonarJavaXmlFileSensor [java] (done) | time=4601ms [INFO] 4/4 source files have been analyzed [INFO] Sensor XML Sensor [xml] [INFO] Sensor XML Sensor [xml] (done) | time=999ms [INFO] Sensor Analyzer for "php.ini" files [php] [INFO] Sensor Analyzer for "php.ini" files [php] (done) | time=3ms [INFO] Sensor JavaScript Squid Sensor [javascript] [INFO] 3 source files to be analyzed [INFO] Unit Test Coverage Sensor is started [INFO] 3/3 source files have been analyzed [INFO] Integration Test Coverage Sensor is started [INFO] Overall Coverage Sensor is started [INFO] Sensor JavaScript Squid Sensor [javascript] (done) | time=6896ms [INFO] Sensor Zero Coverage Sensor [INFO] Sensor Zero Coverage Sensor (done) | time=409ms [INFO] Sensor CPD Block Indexer [INFO] Sensor CPD Block Indexer (done) | time=294ms [INFO] 3 files had no CPD blocks [INFO] Calculating CPD for 10 files [INFO] CPD calculation finished [INFO] Analysis report generated in 896ms, dir size=255 KB [INFO] Analysis reports compressed in 202ms, zip size=111 KB [INFO] Analysis report uploaded in 103ms [INFO] ANALYSIS SUCCESSFUL, you can browse http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/dashboard/index/org.jboss.quickstarts.eap:tasks [INFO] Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report [INFO] More about the report processing at http://sonarqube-xyz-sonarqube80.apps.0845.openshift.opentlc.com/api/ce/task?id=AWWOs4548YCjCIcdKfvG [INFO] Task total time: 56.835 s //代碼分析通過[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 01:26 min [INFO] Finished at: 2018-08-31T06:37:36+00:00 [INFO] Final Memory: 18M/250M [INFO] ------------------------------------------------------------------------ [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (David Publish war to Nexus) [Pipeline] echo David Publish app to Nexus [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + mvn -s ./nexus_openshift_settings.xml deploy -DskipTests=true -DaltDeployment
337/337 B Uploaded: http://nexus3.xyz-nexus80.svc.cluster.local:8081/repository/releases/org/jboss/quickstarts/eap/tasks/maven-metadata.xml (337 B at 11.8 KB/sec) [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 32.726 s [INFO] Finished at: 2018-08-31T06:38:19+00:00 [INFO] Final Memory: 22M/173M [INFO] ------------------------------------------------------------------------ [Pipeline] } [Pipeline] // stage [Pipeline] stage //在Openshift構建docker image,通過B2I 將生成的war包拷貝到builder image中: [Pipeline] { (David Build and Tag OpenShift Image) [Pipeline] echo David Building OpenShift container image tasks:1.1-10 [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc start-build tasks --follow --from-file=./target/openshift-tasks.war -n xyz-tasks-dev80 Uploading file "target/openshift-tasks.war" as binary input for the build ... build "tasks-3" started Receiving source from STDIN as file openshift-tasks.warCopying all war artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment... '/tmp/src/openshift-tasks.war' -> '/opt/eap/standalone/deployments/openshift-tasks.war' Copying all ear artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment... Copying all rar artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment... Copying all jar artifacts from /tmp/src directory into /opt/eap/standalone/deployments for later deployment... Copying all war artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment... Copying all ear artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment... Copying all rar artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment... Copying all jar artifacts from /tmp/src/deployments directory into /opt/eap/standalone/deployments for later deployment... Pushing image docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:latest ... Pushed 6/7 layers, 97% complete Pushed 7/7 layers, 100% complete Push successful [Pipeline] openshiftTag
Starting "Tag OpenShift Image" with the source [image stream:tag] "tasks:latest" from the project "xyz-tasks-dev80" and destination stream(s) "tasks" with tag(s) "1.1-10" from the project "xyz-tasks-dev80". Exiting "Tag OpenShift Image" successfully. [Pipeline] } [Pipeline] // stage [Pipeline] stage //將docker image部署到dev環境,先修改dc指向上一步生成的image,然後觸發dc進行部署:[Pipeline] { (David Deploy app to Dev) [Pipeline] echo David Deploying container image to Development Project [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script+ oc set image dc/tasks tasks=docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:1.1-10 -n xyz-tasks-dev80deploymentconfig "tasks" image updated [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc delete configmap tasks-config -n xyz-tasks-dev80 --ignore-not-found=true configmap "tasks-config" deleted [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc create configmap tasks-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-dev80 configmap "tasks-config" created [Pipeline] openshiftDeployStarting "Trigger OpenShift Deployment" with deployment config "tasks" from the project "xyz-tasks-dev80".Operation will timeout after 600000 milliseconds Exiting "Trigger OpenShift Deployment" successfully; deployment "tasks-3" has completed with status: [Complete]. [Pipeline] openshiftVerifyDeployment Starting "Verify OpenShift Deployment" with deployment config "tasks" from the project "xyz-tasks-dev80". Waiting on the latest deployment for "tasks" to complete ... Operation will timeout after 180000 milliseconds Exiting "Verify OpenShift Deployment" successfully; deployment "tasks-3" has completed with status: [Complete]. [Pipeline] openshiftVerifyService Starting "Verify OpenShift Service" for the service "tasks" from the project "xyz-tasks-dev80". Attempting to connect to "172.30.194.191:8080" ... Exiting "Verify OpenShift Service" successfully; a connection to "172.30.194.191:8080" was made. [Pipeline] } [Pipeline] // stage [Pipeline] stage //進行集成測試,通過curl實現:[Pipeline] { (David Run Integration Tests) [Pipeline] echo David Running Integration Tests [Pipeline] sleep Sleeping for 15 sec [Pipeline] echo Creating task [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + curl -i -u tasks:redhat1 -H 'Content-Length: 0' -X POST http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/integration_test_1 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 100 74 100 74 0 0 54 0 0:00:01 0:00:01 --:--:-- 54 HTTP/1.1 404 Not Found Connection: keep-alive X-Powered-By: Undertow/1 Server: JBoss-EAP/7 Content-Length: 74 Content-Type: text/html Date: Fri, 31 Aug 2018 06:39:23 GMT <html><head><title>Error</title></head><body>404 - Not Found</body></html>[Pipeline] echo Retrieving tasks [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + curl -i -u tasks:redhat1 -H 'Content-Length: 0' -X GET http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 74 100 74 0 0 2575 0 --:--:-- --:--:-- --:--:-- 2642 HTTP/1.1 404 Not Found Connection: keep-alive X-Powered-By: Undertow/1 Server: JBoss-EAP/7 Content-Length: 74 Content-Type: text/html Date: Fri, 31 Aug 2018 06:39:23 GMT <html><head><title>Error</title></head><body>404 - Not Found</body></html>[Pipeline] echo Deleting tasks [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + curl -i -u tasks:redhat1 -H 'Content-Length: 0' -X DELETE http://tasks.xyz-tasks-dev80.svc.cluster.local:8080/ws/tasks/1 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 83 100 83 0 0 5903 0 --:--:-- --:--:-- --:--:-- 6384 HTTP/1.1 405 Method Not Allowed Connection: keep-alive X-Powered-By: Undertow/1 Server: JBoss-EAP/7 Content-Length: 83 Content-Type: text/html Date: Fri, 31 Aug 2018 06:39:23 GMT <html><head><title>Error</title></head><body>405 - Method Not Allowed</body></html>[Pipeline] stage //拷貝deocker image到Nexus Docker Registry中,通過skopeo實現:[Pipeline] { (David Copy Image to Nexus Docker Registry) [Pipeline] echo David Copy image to Nexus Docker Registry [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script ++ oc whoami -t + skopeo copy --src-tls-verify=false --dest-tls-verify=false --src-creds openshift:eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ4eXotamVua2luczgwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImplbmtpbnMtdG9rZW4tcHZjMngiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiamVua2lucyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjVkNTNiZDUzLWFhOWYtMTFlOC1iNWVlLTBhY2Q3NjhhYmEzMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDp4eXotamVua2luczgwOmplbmtpbnMifQ.LwTOxjvWbARVAyh750wU69CefvDgL8w-v9gTkHQ6BeXh4ATkfBYWug4GKJ-XWQxnZIe0oNLUuHg4hJPmzs6OohIcwXk-DUhks_6UMzOXZg0fP68OwpEZTh9nn6ImMmIETO4lm4SZBUcCBYOsEzJPwSuTXV59qqYcGQgVLQ_zya_ucR5zPmxwb-cWI4TAmTCHcH6dOAAZixGQb8ncHjzEFqxRE4HARUZYj5JcICjMABb9wDybXWTwol3gq4W0akkbd56466IYOlhJzCp6OFxGMf6Ze1xwSt5Pwrl4Xn9i1B_-2ZTp7UBNY_SNsBOIb7v0_IQRmucOJfu0ZU6v3W1y-g --dest-creds admin:admin123 docker://docker-registry.default.svc.cluster.local:5000/xyz-tasks-dev80/tasks:1.1-10 docker://nexus-registry.xyz-nexus80.svc.cluster.local:5000/tasks:1.1-10 Getting image source signatures Skipping fetch of repeat blob sha256:243dc7b9e786e952d1a31abe13850c78dbda894bae5f952f1bc83eb7625ced4e Skipping fetch of repeat blob sha256:550516fb1c76cce4ed1e5197ab774186feb529bcc6362b3fe11cb7ab6f331206 Skipping fetch of repeat blob sha256:bd2f45881d4be8c18df36799d455bb6ec52669058c8a35eb65a198608434c195 Skipping fetch of repeat blob sha256:51268d1752f657f09e5c7ab7b564a9254dd3f566fcdcbc92db0d9de8378bb18b Skipping fetch of repeat blob sha256:310ef6e6c91ce656668a4db4719fb0135f4b63a64fd98c423fda98e7a82d4f1d Skipping fetch of repeat blob sha256:7b582c56c1ab9b1a9cb67caa730dcf932c6eb4aeee26b1cfbf8b982bcad446d9 Copying blob sha256:d0af4999de1d5f0bcb977f4b8e73b0246c72850508b5716be9f1093d083c289c 0 B / 3.98 MB 3.98 MB / 3.98 MB 3.98 MB / 3.98 MB 0s Copying config sha256:ddc1196b8d7a08399be99152ab63ac9d7b8760e0d1bd55ae6b765fe97216582e 0 B / 6.71 KB 6.71 KB / 6.71 KB 0s Writing manifest to image destination Storing signatures [Pipeline] openshiftTag Starting "Tag OpenShift Image" with the source [image stream:tag] "tasks:1.1-10" from the project "xyz-tasks-dev80" and destination stream(s) "tasks" with tag(s) "1.1" from the project "xyz-tasks-dev80". Exiting "Tag OpenShift Image" successfully. [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // stage [Pipeline] stage //進行藍綠髮布[Pipeline] { (David do Blue/Green Production Deployment) [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc get route tasks -n xyz-tasks-prod80 -o 'jsonpath={ .spec.to.name }' [Pipeline] echo Active Application: tasks-blue [Pipeline] echo Destination Application: tasks-green [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc set image dc/tasks-green tasks-green=docker-registry.default.svc:5000/xyz-tasks-dev80/tasks:1.1 -n xyz-tasks-prod80 deploymentconfig "tasks-green" image updated [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc delete configmap tasks-green-config -n xyz-tasks-prod80 --ignore-not-found=true configmap "tasks-green-config" deleted [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc create configmap tasks-green-config --from-file=./configuration/application-users.properties --from-file=./configuration/application-roles.properties -n xyz-tasks-prod80 configmap "tasks-green-config" created [Pipeline] openshiftDeploy Starting "Trigger OpenShift Deployment" with deployment config "tasks-green" from the project "xyz-tasks-prod80". Operation will timeout after 600000 milliseconds Exiting "Trigger OpenShift Deployment" successfully; deployment "tasks-green-1" has completed with status: [Complete]. [Pipeline] openshiftVerifyDeployment Starting "Verify OpenShift Deployment" with deployment config "tasks-green" from the project "xyz-tasks-prod80". Waiting on the latest deployment for "tasks-green" to complete and scale to "1" replica(s) ... Operation will timeout after 180000 milliseconds Exiting "Verify OpenShift Deployment" successfully; deployment "tasks-green-1" has completed with status: [Complete]. The deployment reached "1" replica(s). [Pipeline] openshiftVerifyService Starting "Verify OpenShift Service" for the service "tasks-green" from the project "xyz-tasks-prod80". Attempting to connect to "172.30.156.93:8080" ... Exiting "Verify OpenShift Service" successfully; a connection to "172.30.156.93:8080" was made. [Pipeline] } [Pipeline] // stage [Pipeline] stage //提示是否向生產切換[Pipeline] { (David do Switch over to new Version) [Pipeline] input Switch Production? Proceed or Abort Approved by user80 [Pipeline] echo Switching Production application to tasks-green. [Pipeline] sh [xyz-jenkins80-tasks-pipeline] Running shell script + oc patch route tasks -n xyz-tasks-prod80 -p '{"spec":{"to":{"name":"tasks-green"}}}' route "tasks" patched [Pipeline] } [Pipeline] // stage [Pipeline] stage //遷出源[Pipeline] { (David Checkout Source) [Pipeline] checkout > git rev-parse --is-inside-work-tree # timeout=10 Fetching changes from the remote Git repository > git config remote.origin.url http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 # timeout=10 Fetching upstream changes from http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 > git --version # timeout=10 using GIT_ASKPASS to set credentials xyz-jenkins80-gogs-secret > git fetch --tags --progress http://gogs-xyz-gogs80.apps.0845.openshift.opentlc.com/CICDLabs/openshift-tasks-private1 +refs/heads/*:refs/remotes/origin/* > git rev-parse origin/master^{commit} # timeout=10 Checking out Revision 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 (origin/master) > git config core.sparsecheckout # timeout=10 > git checkout -f 6b3cdd2e486420320b09ba84ab6c51e41d1a0642 Commit message: "更新 'Jenkinsfile'" [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS