145 lines
6.7 KiB
TeX
145 lines
6.7 KiB
TeX
\subsubsection{Verifikation}
|
|
\label{ssub:verifikation}
|
|
|
|
Wie auch in der Softwareentwicklung müssen Konfigurationssysteme getestet
|
|
werden. Dies gestaltet sich oft als schwierig, weil nicht immer eine exakte
|
|
Kopie des aktuellen Produktionssystem zur Verfügung steht. Mit steigender
|
|
Komplexität steigt der Aufwand, geschriebene Cookbooks manuell zu testen. Im
|
|
Folgenden werden verschiedene Möglichkeiten aufgeführt, wie dies automatisiert
|
|
werden kann.
|
|
|
|
Die erste und einfachste Methode ist der Befehl:
|
|
|
|
\shellcmd{knife cookbook test [COOKBOOKS...]}
|
|
|
|
Das Kommandozeilenprogramm \emph{knife} ist Teil von Chef. Es ist das primäre
|
|
Verwaltungsprogramm für Adminstratoren. Der Unterbefehl \emph{cookbook test}
|
|
überprüft den Rubyquellcode und die Templates des Cookbooks auf Syntaxfehler.
|
|
Allerdings treten viele Fehler erst zur Laufzeit auf, insbesonderes da Ruby eine
|
|
dynamische Programmiersprache ist. Ein anderes Programm ist foodcritic. Es führt
|
|
eine statische Codeanalyse ähnlich \href{http://www.jslint.com/}{JSlint} oder
|
|
\href{http://perl-critic.stacka.to/}{Perl::Critic} auf der eigenen Codebasis
|
|
durch. Dabei wird der Rubycode gegen einen Regelsatz getestet, um so häufige
|
|
Programmierfehler zu erkennen oder um Codingstandards innerhalb eines Projekts
|
|
einzuhalten. Dieser Regelsatz kann durch eigene Regeln erweitern werden.
|
|
|
|
\textbf{Chefspec}
|
|
\label{chefspec}
|
|
|
|
Chefspec baut auf das, in Ruby verbreitete, Testframework
|
|
\href{http://rspec.info/}{RSpec} auf. Rspec ist ein Testframework, welches auf
|
|
\href{http://dannorth.net/2012/05/31/bdd-is-like-tdd-if/}{Behavior Driven
|
|
Development} (kurz BDD) basiert. Hierbei dokumentieren sich Testcases selbst
|
|
durch Einfügen von Beschreibungen. RSpec kann Sätze aus diesen Beschreibungen
|
|
bilden und so im Falle eines fehlgeschlagen Tests schnell darüber Auskunft
|
|
geben, was der Test getestet hat und aus welchen Grund dieser fehlgeschlagen
|
|
ist. Chefspec erweitert dabei RSpec um die Funktion, Cookbooks zu laden und
|
|
stellt spezielle Matcher (RSpec-Terminologie für Assertions) bereit, um diese zu
|
|
testen. Wie bereits in Abschnitt~\ref{ablauf_einer_provisionierung} erwähnt,
|
|
gibt es zwei Phasen bei der Ausführung von Chef. Bei Chefspec wird der
|
|
Provisionierungsprozess nur bis zur Convergingphase durchlaufen. Die eigenen
|
|
Tests überprüfen nur die erzeugten \emph{Resources}. Dies hat den Vorteil, das
|
|
Tests sehr schnell durchlaufen werden, da keine Änderungen an einem System
|
|
vorgenommen werden müssen. Dies hat Vorteile beim Entwickeln, weil man auf diese
|
|
Weise schnell Feedback bekommt. Das Zusammenspiel mehrerer Cookbooks lässt sich
|
|
dadurch gut testen. Außerdem ermöglicht es, verschiedene
|
|
Konfigurationen/Betriebssysteme durchzutesten, ohne das diese (zeit)aufwendig
|
|
aufgesetzt werden müssen. Da Chefspec allerdings zu keinen Zeitpunkt Code auf
|
|
dem System ausführt, sind weitere Integrationstest unerlässlich.
|
|
|
|
Der folgende Test wurde aus dem selbst geschriebenen NTP-Cookbook
|
|
(\ref{ssub:einrichtung-der-netzwerkdienste}) entnommen.
|
|
|
|
\begin{lstlisting}[language=Ruby]
|
|
require_relative '../spec_helper'
|
|
|
|
describe 'ntp::default' do
|
|
let(:chef_run) do
|
|
ChefSpec::Runner.new do |node|
|
|
node.set["ntp"]["subnets"] = ["::1", "127.0.0.1", "172.28.128.0 mask 255.255.255.0 nomodify notrap nopeer"]
|
|
end.converge(described_recipe)
|
|
end
|
|
|
|
it "should setup ntp" do
|
|
chef_run.should install_package("ntp")
|
|
chef_run.should render_file("/etc/ntp.conf").with_content("172.28.128.0")
|
|
end
|
|
end
|
|
\end{lstlisting}
|
|
|
|
Im \emph{chef\_run}-Block wird der fiktiven Node Attribute zugewiesen und das zu
|
|
testende Cookbook ausgeführt. Das Ergebnis wird in diesem Beispiel in dem Objekt
|
|
\emph{chef\_run} gespeichert. Gegen dieses Objekt wird getestet, ob bestimmte
|
|
\emph{Resources} korrekt initialisiert wurden. In diesem Fall wird überprüft, ob
|
|
das Paket \emph{ntp} installiert werden soll und ob das Subnetz in dem Template
|
|
in der Konfigurationsdatei \emph{/etc/ntp.conf} richtig gesetzt wird.
|
|
|
|
Die Tests werden mit dem Befehl \emph{rspec} ausgeführt. Wenn keine weiteren Argumente
|
|
angegeben sind, führt dieses Programm alle Dateien unterhalb des Ordners \emph{spec}
|
|
aus, dessen Dateinamen auf \emph{\_spec.rb} enden.
|
|
|
|
Um alle drei oben genannten Testmethoden gleichzeitig ausführen zu lassen, wurde
|
|
ein Rakefile geschrieben. \href{http://rake.rubyforge.org/}{Rake} ist das, in
|
|
Ruby geschriebene Äquivalent, zu Make, welches ein verbreitetes Buildprogramm
|
|
auf Unix-Ähnlichen Plattformen ist. Die Tests werden durch den Task \emph{test}
|
|
ausgeführt:
|
|
|
|
\shellcmd{rake test}
|
|
|
|
Dieser muss innerhalb Projektverzeichnises aufgerufen werden.
|
|
|
|
\textbf{Minitest-Handler}
|
|
\label{minitest_handler}
|
|
|
|
\href{https://github.com/btm/minitest-handler}{Minitest-Handler} hingegen wird
|
|
nach jedem Provisionierungsdurchgang ausgeführt. Im Gegensatz zu Chefspec nutzt
|
|
es das Minitest-Framework, welches schon mit Ruby mitgeliefert wird. Allerdings
|
|
kann man durch einbinden, der Zeile:
|
|
|
|
\begin{lstlisting}
|
|
require "minitest/spec"
|
|
\end{lstlisting}
|
|
|
|
eine Syntax benutzen, die RSpec sehr ähnliche ist. Um Minitest-Handler zu
|
|
nutzen, muss das Recipe aus \emph{Minitest-Handler-Cookbook} als erstes Recipe
|
|
in der node geladen werden. Minitest-Handler durchsucht beim Durchlauf in jedem
|
|
anderen Cookbook, in den Unterordnern in \emph{files/} nach dem Verzeichnis
|
|
\emph{test} und lädt alle Tests aus diesem Verzeichnis. Über die
|
|
Beschreibungszeile:
|
|
|
|
\begin{lstlisting}[language=Ruby]
|
|
describe_recipe "ntp::default" do #
|
|
#...
|
|
end
|
|
\end{lstlisting}
|
|
|
|
wird angeben, für welches Recipe der Test gedacht ist (In diesem Fall das
|
|
Defaultrecipe aus dem NTP-Cookbook). Wenn das entsprechende Recipe von der Node
|
|
ausgeführt wird, wird der dazugehörige Test nach dem Provisionierungsdurchlauf
|
|
ebenfalls ausgeführt. Minitest-Handler erweitert RSpec um nützliche Methoden, um
|
|
den Status des Systems zu überprüfen. Nachfolgend ein Beispiel aus dem Bind-Cookbook,
|
|
welches in Abschnitt~\ref{ssub:einrichtung-der-netzwerkdienste} erwähnt wurde:
|
|
|
|
\begin{lstlisting}[language=Ruby]
|
|
describe_recipe 'bind::default' do
|
|
it "starts the named daemon" do
|
|
service("bind9").must_be_running
|
|
end
|
|
it "should resolve dns" do
|
|
assert_sh("dig localhost @localhost")
|
|
end
|
|
end
|
|
\end{lstlisting}
|
|
|
|
Die Methode \emph{assert\_sh} überprüft den Exitstatus eines Befehls und schlägt
|
|
fehl, wenn dieser ungleich Null ist, während die \emph{service}-Methode den
|
|
Status eines Systemdienst sicherstellt. Weitere Testmedhoden sind zum Beispiel
|
|
das Überprüfen von Verzeichnissen, Inhalte von Dateien oder Mountpoints. Viele
|
|
Fehler werden in der Regel schon von den Provider erkannt und festgestellt.
|
|
Minitest-Handler kann dies Erweitern um protokollspezifische Tests durchzuführen
|
|
oder das Testen von Funktionalität bestimmter Dienste.
|
|
|
|
TODO Resume und Ausblick
|
|
|
|
% vim: set spell spelllang=de_de
|