Nedávno na fedora.cz vyšel parádní článek o využití nástroje mock. Přes neocenitelné rady a postupy, které nabídl, však přinesl také zmatení a otázky „Proč je to sakra tak složité?“. V tomto článečku bych rád zmínil základní principy mockování, základní setup a základní použití.

1 – úvod

Hned ze začátku ještě jednou zdůrazním – tvorba vlastního balíčku „from scratch“ není obsahem tohoto článku. Obsahem tohoto článku je představení nástroje mock v jeho nezákladnější podobě, ukázání, jak pomocí něj přestavovat balíčky a jednoduše emulovat prostředí ve změněném kořenu – chroot.

1.1 – setup

yum install mock fedpkg

To jsou jediné dva balíčky (+ jejich závislosti – python, git, chroot…) které budeme potřebovat.

Mock nemá povoleno běžet pod rootem, ovšem sám jistá rozšířená oprávnění potřebuje. Čili buď mu budete při každém běhu zadávat heslo roota nebo se přidáte do skupiny mock– pak už po vás ověření chtít nebude.

2 – získání balíčku a rebuild

Ať již tvoříte balíček nový, nebo modifikujete existující, nástroje fedora-packager vám s tím mohou hodně pomoci. Nástroji rpmbuild (který je stále jednou z nejzákladnějších jednotekmocku i fedpkg) bych se v tomto článku rád vyhnul, neb je to složitá tematika sama o sobě, a mock i fedpkg od něj člověka šťastně odstiňují.

2.1 – naklonování balíčku

Pokud máte účet ve Fedoře a balíček nemá speciální oprávnění, pak jednoduše:

fedpkg clone -B názevBalíčku

Parametr -B naklonuje všechny větve (branches) git repozitáře z http://pkgs.fedoraproject.org/cgit/nazevBaliku.git/ – tzn. všechny verze Fedory, ve kterých se balíček vyskytuje. Pokud byste je vynechali, pak vám naklonuje head všech větví – čili verzi pro rawhide – pro příští Fedoru, a vy budete marně hledat stabilní verzi balíčku. Stále budete mít ovšem možnost přepínat mezi větvemi pomocí gitu – git checkout větev, kde větev je master, nebo fX, kde X je verze Fedory – například F19, F18…

Čili pro náš ukázkový příklad:

fedpkg clone -B jpanoramamaker.

Pokud účet nevlastníte, pak:

git clone git://pkgs.fedoraproject.org/nazevBaliku

je vaším anonymním přítelem.

2.2 – srpm

Srpm je balíček, který obsahuje všechna potřebná data (a metadata!) k vytvoření balíčků samotných. Nástroj fedpkg má pro naše potřeby „urychlovátko“ v podobě fedpkg srpm ve vybrané větvi. Ukázka pro jpanoramamaker a Fedoru 19:

git clone git://pkgs.fedoraproject.org/jpanoramamaker
cd jpanoramamaker
git checkout f19
fedpkg --dist f19 srpm

Pokud by byl balíček váš, celé se to zjednoduší:

fedpkg clone -B jpanoramamaker
cd jpanoramamake/f19
fedpkg srpm

Během fedpkg srpm se stáhly všechny potřebné zdroje a vše, včetně souboru .spec (a případných v něm definovaných dalších souborů), se zabalilo do archivu rpm cpio, jehož jméno vždy obsahuje názevBalíčku, plnou verzi včetně označení distribuce a příponu .src.rpm. Archivem můžete procházet pomocí Midnight Commanderu nebo aplikace file-roler a podobných. Z naší ukázky (v době psaní článku) vypadlo jpanoramamaker-5.4-3.fc19.src.rpm.

2.3 – konfigurace mocku

Mock je nástroj, který umí omezeně emulovat systém v systému (neplést s virtualizací!) a neuvěřitelně zjednodušuje sestavování balíčku v „čistém systému“ – na rozdíl od nástroje rpmbuild, který sestavuje balíčky přímo ve vašem systému (s vašimi závislostmi a konfiguracemi). Ne že by váš systém byl zaneřáděný nebo naopak vám ho rpmbuild zanesl, ovšem můžete mít nějaké speciální verze knihoven nebo nějaké nestandardní nástroje a to by u balíčku, který by měl být někomu poslán, mohlo být naškodu. A nebo nechcete balíček vůbec pro váš systém.

Proto se mock spouští s parametrem systému – nejen názvu systému, ale i jeho verze a architektury. K tomu slouží přepínač -r konfigurace. Kde konfigurace je dle konvence název-verze-architektura. Například fedora-18-ppc nebo epel-5-i386. Tyto jména nejsou ničím jiným než klíčem souboru .cfg v /etc/mock/.

Tyto soubory (např. /etc/mock/epel-4-i386.cfg) jsou velmi jednoduché a obsahují jen trošku konfigurace a URL, kde najít repositář. Není tedy žádný problém si nachystat vlastí „distribuci“.

Součástí mocku je velké množství konfiguráků pro všemožné rpm-based distribuce, a není nic lehčího, než je použít.

2.4 – rebuild

Když víme, pro jakou konfiguraci chceme sestavovat, můžeme snadno spustit mock, například:

mock -r fedora-19-x86_64 jpanoramamaker-5.4-3.fc19.src.rpm

Z toho příkazu jsou již jasné výhody mocku – nepotřebujete rpmbuild, nepotřebujete závislosti, vlastně nepotřebujete ani systém. Mock všechno obstará za vás a navíc vám (omezeně) umožní simulovat architekturu. Toto omezení většinou závisí na typu architektury. Čili na čipech intelu můžete mockovat 64b i 32b varianty, ale PPC si tam nenasimulujete. Stejně tak na ARMu sestavíte všechny varianty ARMu, ale intely nenasimulujete. Mock vás o tom většinou informuje hned v začátku, takže žádný strach.

Výsledky se pak nalézají ve /var/lib/mock/os-verze-arch/results, včetně logů. Systém sám se schovává ve /var/lib/mock/os-verze-arch/root a build v builddir/build.

2.5 – „mock shell“

Do mockového prostředí – přesněji do jeho příkazové řádky – lze snadno vstoupit pomocí --shell. Roota tam máte automaticky.

mock -r konfigurace --shell

Nezapomeňte, že daný „systém“ není nic jiného než obsah již zmíněného /var/lib/mock/os-verze-arch/root. Takže tam můžete zvenku snadno zasahovat. Daný „systém“ je většinou hodně minimalistický a i když má všechny potřebné komponenty pro sestavení vašeho balíčku, často nemá vše potřebné pro jeho instalaci. A také většinou nemá žádný X-server. Pokud v tomto „systému“ chcete balíček nějak výrazněji testovat (to znamená vše složitější než rpm -ivh --nodeps balíček), chce to přidat (dočasně!!) do spec souboru BuildRequires yum apo buildu si chroot trošku upravit.

Ze shellu se odhlásíte jako z každého jiného shellu.

3 – úprava balíčku a jeho „distribuce“

Pokud se ve vašem prostředí používá nějaký mírně modifikovaný balíček, ale nestojí za to tvořit vlastní repositář, pak je mock ideální pomocník. Umožní vám sestavit váš modifikovaný balíček pro různá prostředí a navíc v čistém systému a s možností otestování, a nenutí vás instalovat si všelijaké zvrhlé knihovny potřebné pro kompilaci. Mimochodem, následující nemá sloužit jako návod pro nějaké nekalé praktiky, ale jako shrnutí a ukázka základních vlastností mocku.

3.1 – úpravy v kódu a ve zdrojích

Pokud si člověk nějak drobně modifikuje balíček, pak nejčistší volbou je „opatchování“ zdrojových kódů. Pokud chce nahradit binární blob, pak musí binární blob dodat nebo si zfalšovat samotný zdrojový archiv. Protože při vývoji se občas hodí oboje, oboje si teď ukážeme. Za příklad opět poslouží anonymně naklonovaný jpanoramamaker.

3.1.1 – patch

Patch je textový soubor, který popisuje změnu mezi dvěma textovými soubory. Aby se jeden z nich změnil na druhý pomocí patche, je patch aplikován nástrojem patch. Cílový soubor je většinou specifikován přímo v souboru se změnami a k jeho aplikaci slouží příkaz

patch -p1 < změny.patch

Za zmínku stojí přepínače p0pN, které nám říkají, kolik kousků relativni cesty se má useknout, aby se našel soubor k patchování, a přepínač -R, který otočí (revert) směr aplikace patche.

Nyní tedy malinko pozměníme GUI jpanoramamakeru.

Rozbalíme (kamkoliv) a vstoupíme do adresáře jpanoramamaker-5/src/panoramajoinner. Zazálohujeme PanoramaMaker.java jako PanoramaMaker-orig.java. K nejsnadnějšímu vytvoření jednoduchého patche použijeme program meld:

meld PanoramaMaker-orig.java PanoramaMaker.java

V pravém okně – PanoramaMaker.java – pak změníme některé popisky tlačítek. Klikneme na File->Format as patch a uložíme do adresáře, kde jsou naklonované soubory z GITu Fedory. Například jako lokalize.patch s následujícím obsahem:

--- /home/jvanek/jpanoramamaker/jpanoramamaker-5/src/panoramajoinner/PanoramaMaker-orig.java 
+++ /home/jvanek/jpanoramamaker/jpanoramamaker-5/src/panoramajoinner/PanoramaMaker.java 
@@ -392,35 +392,35 @@ 
 
         jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); 
 
-        jButton5.setText("Clear all"); 
+        jButton5.setText("Vše smazat"); 
         jButton5.addActionListener(new java.awt.event.ActionListener() { 
             public void actionPerformed(java.awt.event.ActionEvent evt) { 
                 jButton5ActionPerformed(evt); 
             } 
         }); 
 
-        jButton4.setText("Load"); 
+        jButton4.setText("Načíst"); 
         jButton4.addActionListener(new java.awt.event.ActionListener() { 
             public void actionPerformed(java.awt.event.ActionEvent evt) { 
                 jButton4ActionPerformed(evt); 
             } 
         }); 
 
-        jButton3.setText("Save "); 
+        jButton3.setText("Uložit "); 
         jButton3.addActionListener(new java.awt.event.ActionListener() { 
             public void actionPerformed(java.awt.event.ActionEvent evt) { 
                 jButton3ActionPerformed(evt); 
             } 
         }); 
 
-        jButton2.setText("Export"); 
+        jButton2.setText("Exportovat"); 
         jButton2.addActionListener(new java.awt.event.ActionListener() { 
             public void actionPerformed(java.awt.event.ActionEvent evt) { 
                 jButton2ActionPerformed(evt); 
             } 
         }); 
 
-        jButton1.setText("Add fotos"); 
+        jButton1.setText("Přidta fotografie"); 
         jButton1.addActionListener(new java.awt.event.ActionListener() { 
             public void actionPerformed(java.awt.event.ActionEvent evt) { 
                 jButton1ActionPerformed(evt);

Meld má někdy potíže s jinými než linuxovými konci řádků, takže vám možná nezbude nic jiného, než použít starý dobrý diff -u PanoramaMaker-orig.java PanoramaMaker.java

Poslední, co je potřeba, je informovat specfile že patch existuje, proto specfile mírně upravíme:

--- jpanoramamaker.spec 
+++ jpanoramamaker.spec 
@@ -1,6 +1,6 @@ 
 Name:           jpanoramamaker 
 Version:        5.4 
-Release:        3%{?dist} 
+Release:        4.custom1%{?dist} 
 Summary:        Tool for stitching photos to panorama in linear curved space 
 BuildArch:      noarch 
 
@@ -9,6 +9,7 @@ 
 License:        BSD 
 URL:            http://jpanoramamaker.wz.cz 
 Source0:        http://jpanoramamaker.wz.cz/fedora/%{name}-5.4.src.tar.gz 
+Patch0:		localize.patch 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 
 
 BuildRequires:  jpackage-utils 
@@ -39,6 +40,7 @@ 
 %prep 
 %setup -q -n %{name}-5 
 
+%patch0 -p5 
 
 find -name '*.class' -exec rm -f '{}' \; 
 find -name '*.jar' -exec rm -f '{}' \; 

3.1.2 – podvrhnutí zdrojů

Druhou změnu, kterou chceme udělat, je změnit tu strašlivou ikonku. Nejjednodušší způsob, jak to udělat, je změnit obrázek přímo v archivu se zdrojovými kódy. Čili si ve svém oblíbeném správci archivů otevřete jpanoramamaker-5.4.src.tar.gz, vstupte do jpanoramamaker-5, otevřete jpanoramamaker.png a nějak jej přečmárejte. Ačkoliv většina správců archívů umí archív aktualizovat, po zavření obrázkového editoru se ujistěte že v archivu je ten správný.

Pomocí „falešných“ zdrojů můžete balíček sestavit nebo vyrobit jeho srpm v rpmbuildu, ale líné osoby zvyklé na komfort fedpkg srpm narazí na problém. Fedpkg totiž pravost zdrojů ověřuje proti souboru sources. Pokud mají zdroje jiný kontrolní součet, pak se pokusí stáhnout ty pravé. Abychom ho umlčeli, podstrčíme do sources jednoduše falešný součet:

md5sum jpanoramamaker-5.4.src.tar.gz > sources

3.2 – rebuild a instalace v chroot

Fedpkg srpm si nyní již stěžovat nebude a src.rpm vám vytvoří. Výsledkem bude jpanoramamaker-5.4-4.custom1.fc19.src.rpm, které je základem pro MOCKovou stavební mašinérii.

Grafik ve sklepě má 64bitovou Fedoru 19, dcera sekretářky z druhého patra má 32bitovou Fedoru 18 a navíc šéfův syn má pořád RHEL 5 – vy si aspoň nebudete muset instalovat tu protivnou javu7… a navíc devel!

mock -r fedora-19-x86_64 jpanoramamaker-5.4-4.custom1.fc19.src.rpm &
mock -r fedora-18-i686 jpanoramamaker-5.4-4.custom1.fc19.src.rpm &
mock -r epel-5-i686 jpanoramamaker-5.4-4.custom1.fc19.src.rpm &
mock -r epel-5-x86_64 jpanoramamaker-5.4-4.custom1.fc19.src.rpm

Za pár minut je hotovo a můžete jim šťastně odeslat RPM, která se snadno nainstalují:

yum install *.rpm

Jako drobnou kontrolu můžete ještě provést instalaci v chroot:

mock -r epel-5-i686 --shell
cd builddir/build/RPMS
rpm -ivh *.rpm

4 – závěr

4.1 – úklid

Důležitou vlastností mocku je, že cachuje čisté sestavovací kořenové adresáře. Přes nepochybné výhody v urychlení a šetření internetového provozu zabírá komprimovaný „systém“ místo na disku. V okamžiku, kdy je práce s daným os-verze-arch na delší dobu, může se hodit jej vyčistit. K tomu slouží přepínač --scrub, opět zároveň spolu s os-verze-arch, který chceme čistit. Sám scrub se píše jako --scrub=akce, kde akce je jeden z all, chroot, cache, root-cache, c-cache, yum-cache. Příklad:

mock -r fedora-19-x86_64 --scrub=all

4.2 – shrnutí

Po přečtení tohoto článku by každý linuxový uživatel měl být schopen používat mock, chápat základní principy drobných úprav v balíčcích a umět je znovu sestavit pro různé (podobné) architektury a systémy.

4.3 – zdroje

https://fedoraproject.org/wiki/Using_Fedora_GIT
http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging
http://linux.die.net/man/1/mock