めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

OpenShiftの内部構造についての覚書 (3)

OpenShiftでお手軽CI環境を作る話です。

Jenkinsカートリッジの利用

OpenShiftでは、Jenkinsが稼働するギアを用意することができます。Webアプリケーションが稼働するギアに、「Jenkins Client」のカートリッジを入れると、「git push」した後のビルド処理がJenkins上で実施されるようになります。これにより、過去のビルド履歴を管理したり、Jenkins上でビルド処理のカスタマイズなども可能になります。また、Jenkinsを使わない場合、ビルド処理は、各アプリケーションのギア上で直接に行われるため、ビルドに失敗すると、アプリケーションが停止するなどの危険性がありますが、それを避けることもできます。

ここでは、例として、TomcatのアプリケーションをJenkinsでビルドする環境を用意してみます。

なお、Jenkinsによるビルド処理のタイミングで、Jenkinsが稼働するギアとは別に、ビルド処理用のギアが立ち上がります。OpenShift Onlineの無償版では、ギアは3個までに制限されているので、以下の作業は、全てのアプリケーションを削除してから実施してください。(Tomcat/Jenkins/ビルド用で、ちょうど3個のギアを消費します。)Jenkinsによるビルド処理の流れは、こちらに記載があります。

Tomcat環境の用意

OpenShiftでは、「JBoss EWS」カートリッジにより、Tomcatが利用できます。(ちなみに、「JBoss EWS/Enterprise Web Server」は、Red Hatの商用サポート付きのTomcatベースのWebアプリケーションサーバ製品です。)

# rhc app create -a tomcat -t jbossews-1.0
Password: ********

Creating application 'tomcat'
=============================

  Scaling:   no
  Namespace: enakaidom
  Cartridge: jbossews-1.0
  Gear Size: default
...

いつもの(?)デフォルトコンテンツが用意されていますが、gitの練習を兼ねて、GitHubで公開されているサンプルアプリケーションをpullしてみます。

# cd tomcat
# git config --global user.email "xxxxxx"
# git config --global user.name "E.Nakai"
# git remote add upstream -m master git://github.com/openshift/tomcat6-example.git
# git pull -s recursive -X theirs upstream master
# git push

最後に「git push」すると、ギアにソースが転送されて、ギア上でビルドが走ります。大量の出力がありますが、最初の方に、次の一行が確認できます。

remote: Found pom.xml... attempting to build with 'mvn -e clean package -Popenshift -DskipTests'

JBoss EWSの他に、JBoss EAPなど、Java系のカートリッジでは、上記のMavenコマンドでビルド処理が行われます。したがって、ローカルの「pom.xml」を編集して、ビルド処理をカスタマイズすることも可能です。

ただし・・・、今回は、Jenkinsでビルドすることが目的ですので、これはそのままにして、次に進みます。

Jenkins環境の用意

まず、Jenkinsが稼働するギアを用意します。

# rhc app create -a jenkins -t jenkins-1.4
Password: ********

Creating application 'jenkins'
==============================

  Gear Size: default
  Namespace: enakaidom
  Scaling:   no
  Cartridge: jenkins-1.4
...
Jenkins created successfully.  Please make note of these credentials:

   User: admin
   Password: yWW7qQpmAinC

Note:  You can change your password at:
https://jenkins-enakaidom.rhcloud.com/me/configure

最後に、Jenkinsの管理画面のURLとadminパスワードが表示されていますので、指定のURLを開いてパスワードを変更しておきます。

続いて、既存のTomcat環境に、「Jenkins Client」のカートリッジを追加します。

# rhc cartridge add jenkins-client-1.4 -a tomcat
Password: ********

Adding 'jenkins-client-1.4' to application 'tomcat'
Success
jenkins-client-1.4
==================
  Properties
  ==========
    Job URL = https://jenkins-enakaidom.rhcloud.com/job/tomcat-build/

最後に表示されたURLにアクセスすると、Jenkinsに新たなプロジェクト(tomcat-build)が追加されていることが分かります。

設定を確認すると、ビルド処理は次のシェルスクリプトが指定されています。

source /usr/libexec/openshift/cartridges/abstract/info/lib/jenkins_util

jenkins_rsync 9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com:~/.m2/ ~/.m2/

# Build setup and run user pre_build and build
. ci_build.sh

if [ -e ${OPENSHIFT_REPO_DIR}.openshift/markers/java7 ];
then
  export JAVA_HOME=/etc/alternatives/java_sdk_1.7.0
else
    export JAVA_HOME=/etc/alternatives/java_sdk_1.6.0
fi

export MAVEN_OPTS="$OPENSHIFT_MAVEN_XMX"
mvn --global-settings $OPENSHIFT_MAVEN_MIRROR --version
mvn --global-settings $OPENSHIFT_MAVEN_MIRROR clean package -Popenshift -DskipTests

# Deploy new build

# Stop app
jenkins_stop_app 9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com

# Push content back to application
jenkins_sync_jbossews 9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com

# Configure / start app
$GIT_SSH 9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com deploy.sh

jenkins_start_app 9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com

$GIT_SSH 9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com post_deploy.sh

ソースをrsyncで持ってきて、Mavenでビルドして、再度、rsyncで送り返しているようです。

なお、Jenkinsのプラグインを見ると、「OpenShift Origin Jenkins Cloud Plugin」が追加されています。これで、OpenShiftとの連携を行なっているものと思われます。

少しソースを変更して、pushしてみます。

# vi src/main/java/mypackage/Hello.java
(適当に変更)

# git commit -a -m "hoge"
# git push
Counting objects: 13, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (7/7), 581 bytes, done.
Total 7 (delta 2), reused 0 (delta 0)
remote: restart_on_add=false
remote: Executing Jenkins build.
remote: 
remote: You can track your build at https://jenkins-enakaidom.rhcloud.com/job/tomcat-build
remote: 
remote: Waiting for build to schedule..................................Done
remote: Waiting for job to complete.............................................................................Done
remote: SUCCESS
remote: New build has been deployed.
To ssh://9fe0cfff84a745128d2c457f5935ee82@tomcat-enakaidom.rhcloud.com/~/git/tomcat.git/
   c0662ed..6383598  master -> master

画面出力から、Jenkinsにビルドを依頼していることが分かります。Jenkinsの画面で、ビルドの成功が確認できます。


Unit Testの追加

せっかくJenkinsと統合できたわけですので、ビルドプロセスにUnit Testを追加してみましょう。

まず、自動作成されたプロジェクトのビルド設定(ビルド→シェルの実行)を見ると、Mavenのオプションに「skipTests」が指定されているので、これをコメントアウトします。

mvn --global-settings $OPENSHIFT_MAVEN_MIRROR clean package -Popenshift ### -DskipTests

ローカルにあるpom.xmlのに、下記のを追加します。

    <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
    </dependency>

ローカルのソースにテストを追加します。ここでは、デフォルトの必ず成功するテストを入れておきます。。。

src/test/java/mypackage/HelloTest.java

package mypackage;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Unit test for Hello.
 */
public class HelloTest
    extends TestCase
{
    /**
     * Create the test case
     *
     * @param testName name of the test case
     */
    public HelloTest( String testName )
    {
        super( testName );
    }

    /**
     * @return the suite of tests being tested
     */
    public static Test suite()
    {
        return new TestSuite( HelloTest.class );
    }

    /**
     * Rigourous Test :-)
     */
    public void testHello()
    {
        assertTrue( true );
    }
}

あとは、これを commit/push するだけです。

$ git commit -a -m "add unittest"
[master a17b839] add unittest
 1 files changed, 1 insertions(+), 1 deletions(-)

$ git push
Counting objects: 13, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (7/7), 506 bytes, done.
Total 7 (delta 2), reused 0 (delta 0)
remote: restart_on_add=false
remote: Executing Jenkins build.
remote: 
remote: You can track your build at https://jenkins-demo.example.com/job/tomcat-build
remote: 
remote: Waiting for build to schedule....Done
remote: Waiting for job to complete............................................Done
remote: SUCCESS
remote: New build has been deployed.
To ssh://43d9bd0b5b9d44a6a27ea60ca6dbbd66@tomcat-demo.example.com/~/git/tomcat.git/
   5712b64..a17b839  master -> master

Jenkinsのビルドのログをみると、ちゃんとテストフェーズが実行されています。

+ mvn --global-settings /usr/libexec/openshift/cartridges/jbossews-1.0/info/configuration/settings.base.xml clean package -Popenshift
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building tomcat 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ tomcat ---
[INFO] Deleting /var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/target
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ tomcat ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ tomcat ---
[INFO] Compiling 1 source file to /var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ tomcat ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ tomcat ---
[INFO] Compiling 1 source file to /var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ tomcat ---
[INFO] Surefire report directory: /var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/target/surefire-reports
Downloading: http://maven.repository.redhat.com/techpreview/all/org/apache/maven/surefire/surefire-junit3/2.7.2/surefire-junit3-2.7.2.pom

Downloading: http://repo1.maven.org/maven2/org/apache/maven/surefire/surefire-junit3/2.7.2/surefire-junit3-2.7.2.pom
2 KB   
       
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/surefire/surefire-junit3/2.7.2/surefire-junit3-2.7.2.pom (2 KB at 77.2 KB/sec)
Downloading: http://maven.repository.redhat.com/techpreview/all/org/apache/maven/surefire/surefire-providers/2.7.2/surefire-providers-2.7.2.pom
       
Downloading: http://repo1.maven.org/maven2/org/apache/maven/surefire/surefire-providers/2.7.2/surefire-providers-2.7.2.pom
2 KB   
       
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/surefire/surefire-providers/2.7.2/surefire-providers-2.7.2.pom (2 KB at 127.7 KB/sec)
Downloading: http://maven.repository.redhat.com/techpreview/all/org/apache/maven/surefire/surefire-junit3/2.7.2/surefire-junit3-2.7.2.jar
       
Downloading: http://repo1.maven.org/maven2/org/apache/maven/surefire/surefire-junit3/2.7.2/surefire-junit3-2.7.2.jar
4 KB   
8 KB   
12 KB   
14 KB   
15 KB   
19 KB   
23 KB   
26 KB   
        
Downloaded: http://repo1.maven.org/maven2/org/apache/maven/surefire/surefire-junit3/2.7.2/surefire-junit3-2.7.2.jar (26 KB at 1417.9 KB/sec)

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running mypackage.HelloTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.079 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- maven-war-plugin:2.1.1:war (default-war) @ tomcat ---
[INFO] Packaging webapp
[INFO] Assembling webapp [tomcat] in [/var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/target/tomcat]
[INFO] Processing war project
[INFO] Copying webapp resources [/var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/src/main/webapp]
[INFO] Webapp assembled in [110 msecs]
[INFO] Building war: /var/lib/openshift/b1e2b2cf9e9b48d283af30ca8090d3e1/jbossews-1.0/ci/jenkins/workspace/tomcat-build/webapps/ROOT.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 29.184s
[INFO] Finished at: Thu Jan 17 13:49:39 JST 2013
[INFO] Final Memory: 21M/51M
[INFO] ------------------------------------------------------------------------

まだ試していませんが、もし、複数ユーザで環境を共有できれば、お手軽CI環境になりそうですね。ビルドに成功したらデプロイまで自動で行われるので、その上で統合テストまで実施できるのかなと。。。