Beliebte Suchanfragen

Cloud Native

DevOps

IT-Security

Agile Methoden

Java

|
//

Automatisierter Modulimport für OpenCms

15.4.2010 | 5 Minuten Lesezeit

In einem unserer Projekte verwenden wir seit langer Zeit OpenCms als Redaktionssystem, ergänzt um ein Backend zur Realisierung von Fachlogik. Da wir agil arbeiten, haben wir natürlich auch den Anspruch, agil zu testen. Erste Maßnahme in Sprint 1 des aktuellen Teilprojekts war demnach das Aufsetzen einer Umgebung für Continuous Integration. Die zugehörige User Story hatte den Namen „Als Tester möchte ich tagesaktuell testen können, um Fehler frühzeitig zu finden“. Im Folgenden beschreibe ich, wie wir den Anspruch „tagesaktuell“ durch automatisierte Deployments realisiert haben.

Obwohl wir in der echten Zielumgebung sowohl OpenCms als auch die zugehörige Datenbank im Cluster betreiben, entschieden wir uns für die CI-Umgebung, eine einfache Installation auf einem einzelnen Server vorzunehmen. Aus der Erfahrung heraus sind Deployments von OpenCms-Modulen im Cluster technisch komplex, da alle importierten Ressourcen automatisch repliziert werden. Gleiches gilt für die Datenbank. Diese Komplexität vermeiden wir somit auf dem Testsystem. Wir sind uns dabei der Tatsache bewusst, dass wir Fehler die potenziell nur im Cluster auftreten erst nach dem Deployment in die Cluster-Umgebung finden können.

Um tagesaktuell testen zu können, ist natürlich auch ein tägliches Deployment der Cms-Module und der Anwendungen notwendig. Da wir alle Anwendungen und Cms-Module bereits seit längerer Zeit automatisch von Hudson bauen und paketieren lassen, fehlte uns also eigentlich nur noch das Bindeglied zwischen Hudson-Build und Deployment auf der Testumgebung.

Wir haben also Schritte festgelegt, die automatisch passieren müssen:

  1. Nach einem erfolgreichen Hudson-Build muss ein Upload des Artefakts auf den Testserver stattfinden.
  2. Der Testserver muss täglich zu einer definierten Uhrzeit alle von Hudson hochgeladenen Artefakte deployen.
  3. Nach dem Deployment soll eine Mail mit Log-Informationen verschickt werden.

Da Hudson die jeweiligen Builds mit Maven durchführt, war der Upload auf den Testserver einfach zu realisieren. Hierfür haben wir einen Ant-Call in die deploy-Phase eingehängt, der mittels SCP das Artefakt auf die Testmaschine kopiert.

Nun kommen wir zum eigentlichen Deployment. Für die lokale Entwicklung nutzen wir bereits seit mehreren Jahren Features der OpenCms Shell. Hiermit synchronisieren wir die Module zwischen Eclipse und OpenCms, und importieren unter anderem auch komplette Sites mit Testcontent.

Um ein Modul zu importieren, bedienen wir uns der Shell-Features „loginUser“, „deleteModule“ und „importModule“. Ein Beispiel:

1loginUser Admin admin
2deleteModule de.codecentric.example
3importModule /opt/somewhere/autodeploy/de.codecentric.example.zip
4exit

Hier sind natürlich die Zugangsdaten, der Modulname und der Pfad zum Modul-ZIP anzupassen.

Da wir viele Module parallel entwickeln und auch deployen wollen, haben wir entschieden, dynamisch ein Skript für die OpenCms Shell zu generieren, welches dann ausgeführt wird. Ich zeige nun das kommentierte Bash-Skript, das unser Deployment vorbereitet und durchführt:

1#!/bin/bash
2HOME_DIR=/opt/somewhere
3PACKAGE_DIR=$HOME_DIR/autodeploy
4JBOSS_BIN_DIR=$HOME_DIR/jboss/bin
5JBOSS_SERVER_DIR=$HOME_DIR/jboss/server/opencms
6OPENCMS_BASE=$JBOSS_SERVER_DIR/deploy/cms.war/WEB-INF
7 
8LOG_FILE=$PACKAGE_DIR/log
9LOG_MAILTO=receiver@example.net
10LOG_MAILFROM=autodeploy@yourhost
11 
12CMS_USER=Admin
13CMS_PASSWORD=admin
14 
15JAVA=/opt/jdk1.6.0_12/bin/java

Nun sind alle wesentlichen Variablen gesetzt. Eine Convenience-Methode für das Auflisten der gefundenen Module folgt:

1function list {
2    if [ 0 != $# ]; then
3        echo "Folgende Module wurden gefunden:"
4        i=1
5 
6        for package in $@
7        do
8                echo "  $i. `basename "$package"`"
9                ((i=$i+1))
10        done
11    else
12    echo -e "Keine Module gefunden.\n"
13    fi
14}

Es folgt das Herzstück unseres Skripts: die deploy-Funktion. Als Parameter erhält sie eine Liste von Pfaden zu ZIP-Files, also zu den Cms-Modulen, die deployed werden sollen. Nur wenn diese Liste nicht leer ist, wird das Cms-Shell-Skript generiert. Alles was nach dem Hinzufügen von „exit“ zu dem Skript noch folgt ist kopiert aus der mitgelieferten cmsshell.sh (siehe WEB-INF des WARs) und ein wenig angepasst. Der nötige Classpath wird befüllt, anschließend wird die Cms-Shell mit dem vorher generierten Skript gestartet und das Deployment der Module findet statt. Eine letzte Anmerkung: wir haben hier noch „purgeJspRepository“ eingefügt, um sicherzustellen dass alle eventuell im FlexCache befindlichen JSP-Fragmente entfernt werden.

1function deploy {
2    if [ 0 != $# ]; then
3    cd $PACKAGE_DIR
4 
5    # Add login statement to the CMS script
6    echo "loginUser $CMS_USER $CMS_PASSWORD" > script
7 
8    # Add import statements to the CMS script
9    for zipfile in $@
10    do
11        echo "deleteModule \"`basename $zipfile .zip`\"" >> script
12        echo "importModule \"$zipfile\"" >> script
13    done
14 
15    # Purge JSP Repo
16    echo "purgeJSPRepository" >> script
17 
18    # Add exit statement to the CMS script
19    echo "exit" >> script
20 
21    for JAR in $JBOSS_SERVER_DIR/lib/*.jar; do
22        TOMCAT_CLASSPATH="$TOMCAT_CLASSPATH:$JAR"
23    done
24 
25    OPENCMS_CLASSPATH=""
26    for JAR in $JBOSS_SERVER_DIR/deploy/web.war/WEB-INF/lib/*.jar; do
27        OPENCMS_CLASSPATH="$OPENCMS_CLASSPATH:$JAR"
28    done
29 
30    $JAVA -classpath "$OPENCMS_CLASSPATH:$TOMCAT_CLASSPATH:classes" org.opencms.main.CmsShell -base="$OPENCMS_BASE" -script=script >> $LOG_FILE
31    fi
32}

Das Skript enthält ansonsten noch einige Hilfsmethoden, die (in unserem Fall) JBoss stoppen und starten, die Mail mit dem Log versenden und nach dem Deployment aufräumen:

1function stopJBOSS {
2    $JBOSS_BIN_DIR/shutdown.sh
3    tail -f $JBOSS_SERVER_DIR/log/server.log > $PACKAGE_DIR/jboss_down.log &
4    until tail -n 1 $JBOSS_SERVER_DIR/log/server.log | grep "Shutdown complete"; do sleep 0.01; done
5    killall tail
6}
7 
8function startJBOSS {
9    rm $JBOSS_SERVER_DIR/tmp/* -r
10    rm $JBOSS_SERVER_DIR/work/* -r
11    $JBOSS_BIN_DIR/startup.sh
12    tail -f $JBOSS_SERVER_DIR/log/server.log > $PACKAGE_DIR/jboss_up.log &
13    until tail -n 1 $JBOSS_SERVER_DIR/log/server.log | grep "Started"; do sleep 0.01; done
14    killall tail
15}
16 
17function mailLog {
18    mailsubject="Auto-Deploy-Log vom `date "+%d.%m.%Y, %H:%M Uhr"`" 
19    cat $LOG_FILE $PACKAGE_DIR/jboss_down.log $PACKAGE_DIR/jboss_up.log | mail -s "$mailsubject" $LOG_MAILTO -a "From: $LOG_MAILFROM"
20}
21 
22function cleanup {
23    rm $PACKAGE_DIR/*
24}

Hier ist zu beachten, dass startup.sh und shutdown.sh nicht zur normalen JBoss-Distribution gehören sondern selbstgemachte Wrapper-Skripte sind.

Dann fehlt eigentlich nur noch der Teil des Skripts, der die tatsächliche Arbeit erledigt:

1echo -e "Suche nach Modulen in: $PACKAGE_DIR"
2 
3packages=`find $PACKAGE_DIR -name *.zip`
4 
5# Do some work! :)
6stopJBOSS
7list $packages
8deploy $packages
9startJBOSS
10mailLog
11cleanup

Wie man sieht, werden hier einfach aus dem PACKAGE_DIR alle dort befindlichen ZIPs als OpenCms-Module betrachtet und deployed. Unsere aktuell im Einsatz befindliche Version des Skripts tut noch einige weitere Dinge – zum Beispiel werden WAR-Files automatisch deployed, es werden Regeln für eine der Anwendungen aktualisiert, und zukünftig werden auch SQL-Skripte automatisch bei jedem Deployment ausgeführt. Das Skript ist natürlich frei nach dem persönlichen Geschmack erweiter- und änderbar.

Mit Hilfe dieses Skripts erfüllen wir passgenau die Anforderung „Als Tester möchte ich tagesaktuell testen können, um Fehler frühzeitig zu finden“. Notfalls kann das Skript sogar während des Tages manuell angestoßen werden um schnell einen Bugfix deployen und testen zu können. Selbstverständlich laufen nach dem automatischen Deployment auch sofort unsere automatisierten Fachtests. Wir haben also eine sehr gute und sehr agile Umgebung für Continuous Integration geschaffen, die uns beim Entwickeln qualitativ hochwertiger Software erheblich unterstützt.

Eine Notiz zum Ende dieses Artikels: ursprünglich wurde unser Autodeploy-Skript nur in Kombination mit OpenCms 7.5.2 und JBoss 4.2.3 genutzt. Mittlerweile hat ein anderes Projekt bei uns im Haus das Skript auch für automatisierte Deployments im Kontext von BEA WebLogic erfolgreich zum Einsatz gebracht.

Für die Zukunft überlegen wir, eventuell auch Deployments in die Zielumgebung, zumindest auf die erste von drei Stages, zumindest partiell zu automatisieren. Wir werden sehen, ob OCEE (Infos zu OCEE hier ) sich mit der Cms Shell verträgt. Wenn dazu schon jemand Erfahrungen hat, freue ich mich über entsprechende Kommentare.

|

Beitrag teilen

Gefällt mir

0

//

Weitere Artikel in diesem Themenbereich

Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.

//

Gemeinsam bessere Projekte umsetzen.

Wir helfen deinem Unternehmen.

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.