Puppet (tisková verze)

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání
Verze k tisku již není podporovaná a může obsahovat chyby s vykreslováním. Aktualizujte si prosím záložky ve svém prohlížeči a použijte prosím zabudovanou funkci prohlížeče pro tisknutí.

Úvodní seznámení

Puppet je systém typu klient/server pro automatickou údržbu operačního systému. Přičemž stroj, na kterém běží server (master), může být zároveň spravován i jako klient (agent) - stejně jako jiné stroje[1].

Puppet pro popis stavu operačního systému používá tzv. doménově specifický jazyk (zkráceně DSL), který je z hlediska syntaxe velmi podobný jazykům s podporou objektového programování(python, php5, java...)[2][3]

Výsledkem zpracování je tzv. manifest - XML soubor, který popisuje jak má systém klientského nodu vypadat. Klientská aplikace která si jej stáhne pak podle něj realizuje potřebné operace. Řeší však pouze to, co je popsáno v manifestu. Aplikace, které nejsou udržovány přes Puppetu, neřeší, pokud jejich konfigurace nějakým způsobem nezasahuje do jím udržované konfigurace.

Upozornění Puppet není systém, který by sám od sebe automaticky zajišťoval kompletní výchozí instalaci, neboť vyžaduje aby na klientské stanici byl přítomen agent.

Nicméně umožňuje výrazným způsobem takovou instalaci usnadnit. Jak instalaci stroj krok za krokem s pomocí Puppetu se můžete dozvědět z manuálu Jak vytvořit bezdiskový stroj s operačním systémem GNU/Linux

Až by se mohlo zdát, že Puppet je primárně určen pro správu linuxového systému, není tomu tak. Interně je naprogramován v Ruby a tak jej lze provozovat i na jiných platformách, jako je MS Windows či MAC OS X. A skrz linuxový server lze spravovat nejenom linuxové nody.

nod
V rámci systému Puppet se rozumí pod pojmem nod stroj na kterém běží agent
manifest
XML soubor, který je výsledkem zpracování skriptů s příponou .pp uložených v adresáři s názvem manifests na stroji, kde běží master. Agent na klientském nodu na základě tohoto manifestu zajistí aby byl jeho systém odpovídajícím způsobem nainstalován a zkonfigurován.
  1. Více o systému Puppet a jeho využití viz Brixí,M.: Automatizace procesů firmy v oblasti správy a údržby serverů (Diplomová práce) Plzeň: ZČU FAV, 2010
  2. Takových systémů je více. Na webu LINUX MAGAZINE[1] (19.8.2010) lze nalézt srovnání čtyři nejrozšířenějších.
    Kromě Puppetu je tam zmíněn Bcfg2, Cfengie a Chef. Puppet se od nich liší právě aplikací DSL.
  3. Skriptu napsanému v DSL se mění kontext podle domény, která jej zrovna interpretuje.
direction a suivre 3 yve 01.svgČíst dále..


Instalace

Většinou je u linuxových distribucí Puppet k dispozici v jejich repozitářích a jeho instalaci tak lze provést přes standardní balíčkovací systém. Výchozí konfigurace však nemusí být všude stejná. Může být jiné nastavení cest k adresářům, moduly manifestu, a bůhví co ještě. Postupy a příklady s nimiž se lze tady setkat sice byly zpracované pro Debian, měly by však být použitelné univerzálně i přes to, že se u novějších verzí mohou v něčem lišit, neboť Puppet se stále vyvíjí.[1]

K archivaci veškerých změn při úpravách manifestů na stroji master je vhodné používat nějaký verzovací systém. Obecně je doporučován git. Pokud je na stroji nainstalován etckeeper, tak by se v podstatě nemuselo nic víc řešit, ale z praktického hlediska je lepší pro adresář /etc/puppet udržovat samostatný repozitář, a do něj po každé úpravě provádět uložení aktuálních změn, včetně komentářů. Mně osobně se osvědčilo přidat do tohoto adresáře i úložiště ssl certifikátů.


Jak už bylo zmíněno úvodem, Puppet je aplikace typu server/klient. Do verze 2.6 se používaly samostatné skripty, ale od verze 2.6 se používá jak pro server, tak klienta jeden a ten samý skript, psaný v Ruby, který může běžet v různých režimech, v závislosti na tom, jaký je předán první argument.

Pre-2.6 Post-2.6 Popis
puppetmasterd puppet master Serverový režim pro centralizovanou správu manifestů (server)
puppetd puppet agent Režim agent pracující s centrálně udržovaným manifestem (klient)
puppet puppet apply Režim agent, pracující s lokálním manifestem (klient bez síťové konektivity)
puppetca puppet cert Režim pro práci s certifikáty (server)
ralsh puppet resource Interaktivní agent (klient)
puppetrun puppet kick Režim při kterém bylo možné vyvolat z jiného stroje vyvolat nějakou akci na straně agenta. V současné době je nahrazen samostatným řešením MCollective
puppetqd puppet queue Režim který odesílal provedené změny do centrální databáze. V současné době je nahrazen aplikací PuppetDB
filebucket puppet filebucket Klient pro práci se soubory v centralizovaném, resp. lokálním úložišti Puppetu (klient)
puppetdoc puppet doc Ze souborů manifestu umí vytáhnout vložené dokumentační řetězce (server), jinak funguje jako aktuální dokumentace k Puppetu.
pi puppet describe Pomůcka pro výpis dokumentace typů a metaparametrů na příkazové řádce (server/klient)

Instalace a konfigurace prostředí stroje master

Chceme-li využívat Puppet pro centralizovanou správu, musíme nejprve nainstalovat stroj co bude fungovat jako server - master, se kterým pak budou komunikovat agenti z klientských nodů. Je dobré od samého počátku počítat s tím, že i tento stroj bude spravován sám sebou a pro tento účel odpovídajícím způsobem pozměnit výchozí konfiguraci.

Pro instalaci serverové části Puppetu je v Debianu balík, který se jmenuje puppetmaster. Od instalačního balíku puppet, který je určen pro klientské nody, se liší především v tom, že obsahuje navíc soubory, které by byly na klientském nodu zbytečné.

Instalace přes standardní balíčkovací systém (APT) je nejrozumnější, neboť se postará o splnění potřebných závislostí:

Poznámka
root@master~# apt-get install puppetmaster

Instalace z repozitářů puppetlabs

U Puppetu platí, že master by měl být vždy novější verze než agent. Je-li na stroji master nainstalován a průběžně aktualizován Debian unstable, tak by neměl vzniknout problém. Pro stable verze Debianu je však lepší nainstalovat master ze zdrojů, které udržuje přímo Puppet Labs, Inc.

Instalaci je třeba začít stažením příslušného .deb balíčku z https://apt.puppetlabs.com/ a jeho "manuální instalací". Viz následující příklad demonstruje stažení balíčku a instalaci pro Debian wheezy

Poznámka
root@master~# wget https://apt.puppetlabs.com/puppetlabs-release-wheezy.deb
...
root@master~# dpkg -i ./puppetlabs-release-wheezy.deb
...
root@master~# apt-get update
...
root@master~# apt-get -t puppetlabs install -y puppetmaster
...
Poznámka Instalační balíček puppetlabs-release-wheezy.deb nainstaluje soubor /etc/apt/sources.list.d/puppetlabs.list který obsahuje záznam pro APT k repozitáři Puppet Labs, Inc., a jejich GPG klíč.

Chcete-li používat stejnou vývojovou verzi Puppetu jako je v unstable, tak před spuštěním aktualizace repozitářů odkomentujte řádky označené jako devel

Úpravy výchozí konfigurace

Konfigurace Puppetu pro všechny módy je v jednom konfiguračním souboru /etc/puppet/puppet.conf, kde má každý z nich svou příslušnou sekci.

main
Obsahuje společné konfigurační volby
master
Obsahuje konfiguraci pro démona v režimu master
agent
Obsahuje konfiguraci pro démona v režimu agent
user
Obsahuje konfiguraci uživatele
Upozornění Do verze 3.6 Puppet používal sekce v tomto konfiguračním souboru pro nastavení prostředí (environment). Kdy každá sekce, jejíž název nepatřil mezi systémové konfigurační bloky (main, master, agent, user) byla interpretovaná jako název prostředí.
V hlavním konfiguračním souboru /etc/puppet/puppet.conf lze změnit výchozí hodnoty proměnných i za běhu démona a dynamicky ovlivňovat prostředí Puppetu. Jinak lze měnit hodnoty výchozích proměnných:
  • nastavením na příkazovém řádku při spuštění démona (prostřednictvím úprav konfiguračních souborů v /etc/default)
  • jednorázově, formou předaných argumentů při akcích na příkazové řádce
  • nebo nastavením proměnných v konfiguračních souborech
Není-li uvedeno jinak, jsou vždy aplikovány výchozí hodnoty.

Úložiště certifikátů

Ve výchozí konfiguraci Debianu Puppet využívá pro všechny režimy (master i klient) stejné úložiště SSL certifikátů, které je v adresáři /var/lib/puppet/ssl. Výchozí konfigurace Puppetu však hledá - není-li uvedeno jinak - certifikáty ve výchozím adresáři /etc/puppet/ssl.

Je-li obsah /etc udržován přes git(resp. etckeeper), je výhodnější používat výchozí nastavení Puppetu. Navíc se tím vyhnete problémům s kolizí certifikátů je-li master spravován přes agenta sám sebou.

  1. Je třeba zastavit spuštěné démony (jak pro režim agent, tak i master)
  2. Zkopírovat adresář s SSL certifikáty z /var/lib/puppet do /etc/puppet.
  3. A před novým spuštěním démona v režimu master zakomentovat řádek v hlavním konfiguračním souboru /etc/puppet/puppet.conf s nastavením proměnné $ssldir
  4. Pro jistotu můžete nakopírovat původní nastavení cesty k úložišti certifikátů do sekce agent. Tím zajistíte, že se klientský certifikát nedostane do kolize se serverovým.

Po spuštění démona v režim master otestujte agenta v testovacím režimu, zda-li je vše v pořádku. Teprve je-li vše ok, ho můžete spustit jako démona.

Spouštění démonů

master

Nahození démona v režimu master lze provést buď přes výchozí init skript..

Poznámka
root@master~# /etc/init.d/puppetmaster start

Nebo spuštěním na příkazovém řádku v režimu master

Poznámka
root@master~# puppet master

Před nahozením však není od věci přesvědčit se, zdali démon v režimu master již neběží. To lze provést buď přímo dotazem přes init skript..

Poznámka
root@master~# /etc/init.d/puppetmaster status
[ ok ] master is running.

..nebo přímo kontrolou spuštěných procesů..

Poznámka
root@master~# ps -ef | grep master
puppet    1849     1  0 srp02 ?        00:16:28 /usr/bin/ruby1.8 /usr/bin/puppet master

Přímé spouštění přes příkazovou řádku má tu výhodu, že můžeme jeho prostřednictvím změnit výchozí konfigurační volby démona. Viz následující příklad pro spuštění démona v ukecaném režimu:

Poznámka
root@master~# puppet master --verbose --debug

Není-li konfigurací určeno jinak, zapisuje démon veškeré zprávy do souboru /var/log/daemons

agent

Pokud chcete stroj, na kterém máte nainstalován Puppet a démona spuštěného v režimu master spravovat přes agenta, tak u Debianu nejspíš narazíte na to, že vám bude chybět init skript pro jeho spouštění. Nezbyde, než ho vytáhnout z instalačního balíku puppet, který je určen pro klienty. Balík lze stáhnout přes APT a pak z něj init skript vytáhnout pomocí dpkg-deb a umístit do adresáře /etc/init.d

Poznámka
root@master~# apt-get -d install puppet
root@master~# dpkg-deb --fsys-tarfile /var/cache/apt/archives/puppet_2.6.2-5+squeeze9_all.deb | tar -xf - ./etc/init.d/puppet
root@master~# mv ./etc/init.d/puppet /etc/init.d/

V každém případě však potom bude nutné upravit spouštění init skriptů tak, aby byl nejprve spuštěn démon v režimu master a až pak v dalším procesu další instance v režimu agent


Manifest

puppet apply.svg

Cílem Puppetu je - udržovat systémové zdroje nodu tak aby konfigurace stroje odpovídala definovanému stavu.

To, v jakém stavu se mají tyto zdroje nacházet je deklarováno, v souborech s příponou .pp, které se nazývají manifesty a popisují jaký má být jejich cílový stav.

Je-li puppet zavolán v módu apply, sestaví z manifestu předaného na příkazové řádce katalog, který pak postupně prochází a přitom kontroluje, zda skutečný stav zdrojů odpovídá tomu deklarovanému.

Pokud ne, tak se ho pokusí uvést do stavu odpovídajícího deklaraci. Tak postupně zpracovává celý katalog, dokud systém neodpovídá definovanému stavu.

Agent/Master

V puppet v režimu agent funguje podobně, ovšem s tím rozdílem, že sestavení katalogu probíhá na straně centrálního úložiště manifestů, kde běží v režimu master.

Agent, který odeslal žádost o katalog na stroj Master, obdrží sestavený katalog a postupně ho kontroluje, tak jako v režimu 'apply. Hlášení o průběhu a výsledku zpracování pak odesílá na Master, který je pak případně distribuuje dále přes e-mail.

puppet agent.svg

Vytvoření manifestu

Manifesty se nazývají soubory, ze kterých se sestavuje katalog, podle kterého pak Puppet kontroluje a nastavuje zdroje tak, aby odpovídaly definovanému stavu systému.

Toto sestavení začíná výchozím manifestem site.pp, který Puppet - pokud nepoužívá jiné prostředí (environment) - hledá v adresáři /etc/puppet/manifests. Ten je bezprostředně po instalaci prázdný a soubor site.pp je nutno vytvořit.

site.pp
By měl obsahovat kód, který bude pro všechny nody společný.

Proměnné

Proměnné jsou objekty, které musí být v rámci jmenného prostoru příslušné třídy (scope) vždy unikátní. Není tedy možné v rámci jednoho scope jejich obsah operativně měnit. Lze je pouze - na základě zpracování kódu v manifestu - nastavit.


Takto deklarovanou proměnnou však lze využívat v nejrůznějších podmínkách, atp. Soubor site.pp je ideálním místem pro nastavení globálních proměnných proto, že pokud Puppet nenajde během zpracování manifestu deklarovaný objekt v rámci jeho jmenného prostoru, prohledává scope manifestu nejvyšší úrovně, kterým je výchozí soubor site.pp.

Proměnné deklarované v jiných třídách lze pochopitelně rovněž používat, musí ale být vždy deklarovány svým plným jménem, které tvoří jméno příslušného jmenného prostoru (třídy) a název proměnné.

$<jmenný prostor proměnné>::<proměnná>
  • Jméno proměnné začíná vždy znakem '$' (znak DOLLAR)
  • K přiřazení hodnoty se používá operátor = (znak "rovná se..").
  • Proměnná může obsahovat řetězec, číslo, pravdivostní hodnotu (false, undef,..), pole nebo kontrolní součet.
  • Proměnnou lze předat jako hodnotu parametru, ale také se dá použít jako jméno zdroje. Zdrojem se rozumí soubor operací, uzavřený ve složených závorkách { }.
  • Proměnné se dají vkládat do řetězců, které musí být uzavřené do uvozovek (znak ").
  • Proměnná, které nebyla přiřazen žádná hodnota vrací řetězec undef
Poznámka Některé verze puppetu mají bug, které při volání globálních proměnných a vyžadují při jejich volání prefix '$::'

Příklad obsahu výchozího souboru /etc/puppet/manifests/site.pp

Poznámka
$puppetserver = 'master.felk.cvut.cz'

V příkladu je nastavena proměnná $puppetserver, která obsahuje doménové jméno stroje, na kterém běží Puppet jako démon v režimu master (nainstalovaný z balíku puppetmaster)

Fakta

Při psaní manifestu lze používat pouze proměnné, ale pro šablony je dostupný ještě jeden zdroj informací - fakta

Fakta jsou informace dostupné pouze na straně klienta, proto se nedají použít při psaní manifestu. Ale lze s nimi pracovat v šablonách, které se budou interpretovat až na straně klienta. To umožňuje generovat konfigurační soubory přímo na míru stroje.


Jaká fakta jsou na nodu dostupná, lze zjistit utilitou facter.

Třídy

Kromě nastavení nodů obsahuje soubor nodes.pp z našeho příkladu také definici společné třídy basic, která bude aplikována na všechny nody, které si ji přes direktivu include natáhnou.

Třídy deklarují, jak mají zdroje v nich popsané na klientském nodu vypadat. Za tímto účelem v sobě obsahují vše potřebné pro realizaci manifestu.


Operace, které jsou nezbytné pro to aby klient odpovídal třídě, se realizují přes tzv. typy. V rámci třídy lze využívat také nejrůznější stavové podmínky, proměnné, integrované funkce, metody, šablony, definice závislostí a třídy z dalších modulů. Viz ukázka použití třídy subclass z modulu modul v rámci třídy basic:

Poznámka
class basic {
      include modul::subclass
    }
Parametrizované třídy

Od verze 2.6.x lze při volání tříd používat parametry. Aplikace takové parametrizované třídy vypadá podobně, jako použití typu, liší se však tím, že její opakované použití na různých místech manifestu nevyvolá chybu. Třída se totiž sama o sobě stará pouze o to aby příslušné věci v systému vypadaly tak jak mají.

Poznámka
class basic ( $editor = 'vim' ){
      if $editor {
         package { "$package":
            ensure => install,
         }
      }
    }

Použití třídy

Použití třídy spočívá v její deklaraci. Tu lze provést několika způsoby, ale vždy pouze jednou. Je-li stejná třída deklarovaná také na jiném místě manifestu, tak už to nemá žádný vliv - nicméně agent proces jeho zpracování neukončí chybou.

Nejčastěji se provádí deklarace prostřednictvím funkce include, jak bylo uvedeno kupř. ve výše umístěném příkladu. Prostřednictvím této funkce lze deklarovat i několik tříd najednou. Jejich názvy přitom musí být odděleny čárkou. Viz příklad.

Poznámka
     include basic, apache, mysql

Od verze 2.5.x lze třídy deklarovat také pomocí funkce require. Ta se využívá především tam, kde je třeba ošetřit závislosti. Kupř. v následujícím příkladu se provede deklarace třídy apache, ještě před zpracováním obsahu definovaného typu apache::vhost, protože konfiguraci virtuálního serveru nelze provést dokud není nainstalován webový server apache.

Poznámka
define apache::vhost ( $port, $docroot, $servername, $vhost_name ){
      require apache
      ...
    }
Upozornění Pozor! Funkce require, která provádí deklaraci třídy, není totéž co metaparametr require, který se používá pro nastavení závislostí

Pro nastavení vzájemných závislostí má Puppet mechanismus, který umožnuje docílit stejného efektu, jako při deklaraci přes funkci require také s využitím funkce include:

define apache::vhost ( $port, $docroot, $servername, $vhost_name ){
      include apache
      Class['apache'] -> Apache::Vhost[$title]
      ...
    }
Použití parametrizované třídy

Bohužel ani jedna z dosud uvedených funkcí neumožňuje deklarovat třídu s použitím parametrů. Jak už bylo zmíněno, parametrizované třídy lze používat od verze 2.6.x a k jejich deklaraci se používá speciální typ class. I když lze pochopitelně parametrizovanou třídu deklarovat také obvyklým způsobem, pokud má být ve výchozím nastavení.

Deklaraci parametrizované třídy basic (viz výše uvedený příklad parametrizované třídy) lze provést tímto způsobem:

Poznámka
class { 'basic':
      editor => 'nano',
    }

V takovém případě by byl v rámci této třídy nainstalován textový editor nano a nikoliv vim, jak by tomu bylo, kdyby byla třída deklarována bez parametru.

Poznámka
class { 'basic': }
Upozornění Pozor! Jakmile je třída jednou deklarovaná, nelze ji deklarovat v rámci aktuálního jmenného prostoru znovu, byť s jiným parametrem!

Nastavení nodu a použití regulárních výrazů

Kromě obecných zdrojů může výchozí manifest obsahovat také deklarace nodů, které mají být přes Puppet spravovány.

Direktiva node vymezuje v deklaraci manifestu blok kódu, který se má použít pro sestavení katalogu pouze pokud jeho identifikátor vyhoví jménu, kterým se ohlásil agent.

Upozornění Bude-li v manifestu nakonfigurováno více nodů, který by mohlo vyhovět jméno agenta, pak Puppet pro sestavení manifestu použije ten, kterému jméno agenta vyhoví nejdřív.
Poznámka Jelikož veškerá komunikace probíhá přes SSL, musí být na stroji master certifikát, který si vyžádal agent nejprve ověřen. Bez něj by totiž master s agentem vůbec nekomunikoval. Identifikátor (doménové jméno stroje ze kterého se agent ohlásil) je součástí tohoto ověřeného certifikátu.

Jako identikátor se může použít celé doménové jméno, ale stačí i jeho zkrácená verze. Pokud identifikátor SSL certifikátu, kterým se agent autorizuje vůči stroji master vyhoví nastavenému řetězeci, pak budou nastavené operace použity při sestavení jeho manifestu.

Příklad deklarace nodu ve výchozím manifestu /etc/puppet/manifests/site.pp :

Poznámka
 #
 # NODE CONFIGURATION
 #
 class basic {
 	}
 node 'master.felk.cvut.cz' {
 	include basic
 	}

Má-li být definice nodu společná více strojům, lze provést přiřazení buď jejich vyjmenováním..

Poznámka
    node 'www.felk.cvut.cz', 'www2.felk.cvut.cz', 'www3.testing.com' {
      include basic
    }

..nebo nastavením regulárního výrazu. Jako regulární výraz bere master řetězec tehdy, jsou-li místo uvozovek použita lomítka

Poznámka
node /^www\d+$/ {
      include basic
    }

Předchozímu regulárnímu výrazu by vyhověly všechny stroje, jejichž (zkrácené) doménové jméno by začínalo řetězcem www následovaným číselnou hodnotou - bez ohledu na doménu ze které by lezly.

Dá se ale použít i složitější podmínka, která vymezí nod pouze vůči strojům petr a pavel z domény felk.cvut.cz.

Poznámka
node /^(petr|pavel)\.felk\.cvut\.cz$/ {
      include basic
    }
default

Normálně se chová Puppet tak, že agenta, jehož doménové jméno, ať plné, nebo zkrácené, nevyhoví žádnému identifikátoru ignoruje.

Jsou však situace, kdy chceme zpuppetizovat každý stroj, bez ohledu na to jaký identifikátor nod pošle. Pro takový případ je třeba založit v manifestu nod default

Poznámka
node default {
      include basic
    }

Dokumentace kódu

Dokumentace k Puppetu je součástí jeho kódu a lze ji v případě potřeby kdykoliv vypsat na příkazové řádce, nebo do souboru. Dokumentaci k manifestu a vlastním modulům si však musíme průběžně psát sami.

  • Popis modulu a informace o tom, jak jej používat, je v souboru README, který se při generování dokumentace hledá v kořenovém adresáři modulu. Je-li nalezen, tak se sloučí dokumentace z kódu a obsah souboru README do jednoho dokumentu, ve jehož rámci lze pak používat pro pohyb v textu hyperlinky.
  • Dokumentace ke třídám (class), uživatelským typům (define) a nódům (node) se vždy umísťuje bezprostředně před dokumentovaný kód a (na rozdíl od souboru README) jako komentář - tj. na řádky které musí začínat mřížkou (#).

Atributy, hodnoty a parametry

Aby byla dokumentace konzistentní, je třeba pokud možno dodržovat jednotnou terminologii. Deklarace zdrojů a parametrizovaných tříd, aj. se vždy skládá z typu a názvu.

Rozdíl je v tom, že zatím co při deklaraci typů a parametrizovaných tříd hovoříme o jejich atributech', u deklarace proměnných a jejich hodnot u metod a implementace tříd hovoříme o parametrech.

puppet doc convetion.svg

Syntaxe

Pro formátování textu integrované dokumentace se používá systém formátovacích značek, které jsou při generování dokumentace interpretovány na HTML kód. Puppet umí zpracovávat dvě formátovací konvence, které se však od sebe vzájemně dost liší:

rdoc
je značkovací systém podobný syntaxi mediawiki, který lze použít k dokumentaci deklarativního kódu v manifestech
markdown
je značkovací systém, který se používá k dokumentaci interního kódu Puppetu, psaného v ruby. k dokumentaci kódu manifestů jej nelze použít!
Poznámka Existuje-li v modulu, soubor README (resp. README.rdoc) bude jeho obsah sloučen s dokumentací k metodám v modulu do jedné stránky. Lze pak na ně odkazovat z jiných stránek dokumentace přes hyperlinky.

README lze formátovat i v markdownu, ovšem pak musí mít tento soubor příponu .md. To platí pro všechny soubory, které používají markdown. U všech ostatních Puppet automaticky předpokládá rdoc. Obsah README.md však nebude integrován s dokumentací metod, neboť v kódu manifestu Puppet akceptuje pouze rdoc a formátovací syntaxi není možné mixovat.

rdoc - zvýraznění textu

Ke zvýraznění textových řetězců se používají následující značky:

* : hvězdička pro ztučnění
_ : podtržítko pro kurzívu
+ : plus pro zvýrazněný strojopis

Řetězec *bold* se tak ve vygenerované dokumentaci objeví jako bold

Upozornění Puppet používá tzv simple rdoc, který má svá specifika. Mezeru chápe jako oddělovač a tak řetězec *bold text* se tak i ve vygenerované dokumentaci objeví jako *bold text*.

Tedy pokud má být zvýraněn textový řetězec který mezery obsahuje, musí být uzavřeno mezi značkami každé slovo zvlášť: *bold* *text*

Bohužel je problém také s interpretací značek pro zvýraznění u řetězců které obsahují diakritiku (bug?), dvojtečku nebo čárku. Tečku, pomlčku nebo lomenou závorku parser zkousne.

rdoc - sekce

Sekce se tak jako u mediawiki oddělují jejich nadpisy, ovšem s tím rozdílem, že formátovací značka není v tomto případě párová

Poznámka
= První úroveň
== Druhá úrověň
=== Třetí úroveň
...
  • Nadpis každé stránky je vždy první úrovně, proto sekce v dokumentaci kódu manifestu by měly začínat od druhé úrovně
  • Z vizuálního hlediska nemá smysl používat víc jak pět úrovní (interpretace nadpisu šesté úrovně se od nadpisu páté úrovně vizuálně neliší)

rdoc - seznamy

Pro vytvoření seznamu používá:

* nebo - : hvězdička nebo pomlčka na začátku řádku pro vytvoření odrážky
1. : Číslo následované tečkou na začátku řádku pro vytvoření číslovaného seznamu
Upozornění Číslované seznamy nelze přerušovat, ani vnořovat. Také jim nelze určit od jaké hodnoty má číslování začít

rdoc - odsazení bloku

Odsazení bloku textu udělají dvě dvojtečky (::).

Upozornění Odsazení textu nelze kombinovat s ukázkami kódu

rdoc - ukázkový kód

Ukázkový kód generuje parser z řádků které začínají minimálně dvěmi mezerami

Upozornění Aby byl kód interpretován jako ukázka kódu, tak mu nesmí předcházet odsazení, nebo popiska bez obsahu. A předchozí blok textu musí být ukončen prázdným řádkem

rdoc - popiska

Popiska se používá kupř. při popisu jednotlivých parametrů či argumentů metod a tříd

Poznámka
[$parametr]
Popis parametru

Je interpretováno jako:

$parametr
Popis parametru

rdoc - hyperlinky

Hyperlinky se generují z řetězců uzavřených do hranatých závorek, který musí předcházet řetězec, který bude interpretován jako odkaz.

Poznámka
Internetový odkaz[url://]

Má-li být vytvořen odkaz z víceslovného řetězce, pak musí být tento řetězec uzavřen do složených závorek

Poznámka
{Internetový odkaz}[url://]

Parser při generování dokumentace do HTML vytváří následující stromovou strukturu

Poznámka
modul.html              # Sloučen obsah souboru README a dokumentace metod modulu modul
modul/modul.html        # Dokumentace k výchozí třídě modulu - modul
modul/modul/class.html  # Dokumentace ke třídě class v modulu modul

Na metody ve výchozím souboru modul.html lze odkazovat pomocí kotev, které mají pevně danou syntaxi. Kotva má k názvu modulu vždy přiřazen řetězec modulmethod-i-

Poznámka
Hyperlinkový odkaz na metodu metoda[#method-i-metoda] v rámci souboru README modulu modul
Poznámka
Hyperlinkový odkaz na metodu metoda[../modul.html#method-i-metoda] z dokumentace k některé třídě či podtřídě modulu modul

Odkazovat lze také na třídy a podtřídy jiných modulů. Viz příklad hyperlinkový odkaz na třídu class v modulu modul z dokumentace k některé třídě či podtřídě v jiném modulu

Poznámka
Link a třídu class[../modul/class.html]

Nebo ukázkový příklad odkazu na podtřídu modul::class::subclass v modulu modul z dokumentace k některému jinému modulu, třídě či podtřídě.

Poznámka
Link na podtřídu modul::class::subclass[../modul/class/subclass.html]
Poznámka U hyperlinků na třídy a podtřídy není nutné řetězec uzavírat do složených závorek, protože dvojtečka není (na rozdíl od mezery) chápána jako odddělovač
Upozornění Dejte si pozor u hyperlinků v dokumentaci nodů. Tam totiž záleží, jesti používáte jeden hlavní manifest site.pp, nebo jestli máte konfiguraci nodů rozdělenou do souborů v adresáři site.pp/. V tom prvním případě stačí u relativní cesty vyskočit pouze o jednu úroveň, kdežto v tom druhém o dvě! Takto: $basic::setwpd[../../basic.html#method-i-setpwd]


rdoc - include

Tato funkcionalita se hodí například pro oddělení kódu, který se stereotypně opakuje v dokumentaci tříd a metod - typicky info o copyrightu. Následující ukázkový kód demonstruje vložení obsahu (formátovaného v rdoc) ze souboru copyright

Poznámka
:include:copyright

Parser ho postupně hledá na několika místech:

  1. Nejprve tam co je dokumentovaný manifest
  2. A potom v kořeni adresáře s konfigurací - Pozor! Nemusí vždy fungovat! V takovém případě lze vyřešit problém pomocí symlinku

Můžeme tedy na tento soubor odkazovat i z jiných modulů nastavením cesty

Poznámka
:include:modules/admins/copyright

V tomto případě natáhne obsah souboru copyright umístěného k kořenovém adresáři modulu admins

Poznámka Stejně jako u souboru README je vkládaný kód obsahem souboru. Můžeme také vkládat obsah jiných manifestů, pak ale musí být vkládaný text ve formě komentáře. Pokud parser dokument nenajde, nevloží nic.



Funkce

Puppet umožňuje při generování manifestů používat kromě integrovaných typů také funkce a metody.

Metody

Metoda, je kontejner definovaný direktivou define, který lze, na rozdíl od třídy, použít opakovaně, s různými parametry - podobně jako funkci, ovšem s tím rozdílem že se volá až při interpretaci manifestu na straně agenta.


Obsahem kontejneru je kód, kterým můžeme dále modifikovat výsledek zpracování manifestu, na základě lokálních fakt a předaných parametrů.

Poznámka
define metoda {
      notify { "Metodě byl předán pouze parametr - $name": }
}
 
metoda { 'jmeno': }

Výsledkem zavolání této metody by bylo pouze vypsání textového řetězce 'Metodě byl předán pouze parametr - jmeno' do logu na straně agenta (přes notify). Nicméně pro demonstraci použití metody tento jednoduchý příklad stačí.

Upozornění Ačkoliv metoda vypadá z hlediska syntaxe zápisu i použití podobně jako parametrizovaná třída, funguje jinak.

Zatím co třídu lze v rámci jednoho jmenného prostoru (scope) deklarovat pouze jednou, ať již s parametry nebo bez, metody lze volat opakovaně. S jedinou podmínkou, a to, že jméno objektu vytvořeného pomocí metody nebude stejné jako má jiný, již existující objekt. V takovém případě agent při zpracování manifestu oznámí chybu a přeruší proces jeho zpracování.

Parametry

Je-li místo textového řetězce metodě předáno pole, nebo proměnná, která pole obsahuje, volá se metoda pro každou položku pole zvlášť, přičemž obsah proměnné $name bude vždy odpovídat jménu aktuální položky. Jak je demonstrováno v následujícím příkladu použití parametrizované metody.

Poznámka
define metoda(
      $parametr = $hodnota,
      $default_parametr = '',
      ) {
      notify { "Hodnota parametru parametr je u položky $name - $parametr":; }
}
 
metoda { [ "A", "B", "C" ]:
      hodnota => "platná"
}
metoda { [ "D", "E", "F" ]:
      hodnota => "neplatná"
}

Výsledkem zpracování výše uvedeného kódu by byly následující vypsané řetězce:

Poznámka
notice: /Stage[main]//Metoda[C]/Notify[Hodnota parametru parametr je u poloÅky C - platnÃ]/
message: is absent, should be Hodnota parametru parametr je u poloÅky C - platnà (noop)
notice: /Stage[main]//Metoda[F]/Notify[Hodnota parametru parametr je u poloÅky F - neplatná]/
message: is absent, should be Hodnota parametru parametr je u poloÅky F - neplatná (noop)
notice: /Stage[main]//Metoda[A]/Notify[Hodnota parametru parametr je u poloÅky A - platnÃ]/
message: is absent, should be Hodnota parametru parametr je u poloÅky A - platnà (noop)
notice: /Stage[main]//Metoda[D]/Notify[Hodnota parametru parametr je u poloÅky D - neplatná]/
message: is absent, should be Hodnota parametru parametr je u poloÅky D - neplatná (noop)
notice: /Stage[main]//Metoda[B]/Notify[Hodnota parametru parametr je u poloÅky B - platnÃ]/
message: is absent, should be Hodnota parametru parametr je u poloÅky B - platnà (noop)
notice: /Stage[main]//Metoda[E]/Notify[Hodnota parametru parametr je u poloÅky E - neplatná]/
message: is absent, should be Hodnota parametru parametr je u poloÅky E - neplatná (noop)
$name
Je parametr kterým disponuje metoda vždy, neboť se do něj při volání metody ukládá jméno volané položky seznamu.
$parametr
Je parametr, do kterého se při volání metody přiřadí hodnota atributu $hodnota. Tento atribut musí být při volání metody nastaven vždy. Kdyby tomu tak nebylo, skončilo by zpracování metody chybou.
$default_parametr
Demonstruje implementaci parametru, který při volání metody nastaven být může, ale nemusí. V takovém případě se při zpracování metody použila jeho deklarovaná hodnota - byť by šlo o prázdný řetězec.


Typy

Typy jsou ve své podstatě předdefinované funkce s parametry, které lze využívat při sestavování vlastních funkcí a tříd.


Příklad použití typu

Pro správu souboru /etc/hosts však můžeme využít existující typ host, přes který lze se záznamy operativně pracovat, aniž by bylo nutné provádět editaci externího souboru.

Typ host pracuje s jednotlivými záznamy. To znamená že v žádném případě původní soubor nepřeplácne. Záznamy, které neodpovídají konfiguraci z původního souboru /etc/hosts překopíruje tak jak jsou, bez ohledu na to zda-li jde o duplicitní záznam, nebo ne.

Upozornění Jakmile se rozhodnete pro údržbu souboru /etc/hosts přes Puppet, tak byste si měli být vědomi skutečnosti, že typ host ignoruje veškeré záznamy v tomto souboru které neodpovídají jím generovanému záznamu.

To platí i pro záznamy které byly vytvořeny před modifikací nastavení typu host! Tzn. že před úpravou by měl být záznam nejprve deaktivován přes parametr ensure nastavený na hodnotu "absent", změna realizována a teprve pak lze manifest modifikovat.

Poznámka
class basic {
    host {"git":
        ip => '147.32.87.200',
        name => 'master',
        comment => "Neexistující stroj";
        host_aliases => "master.felk.cvut.cz",
        ensure => present,
        }
}

Interpretace tohoto kódu by do souboru /etc/hosts přidala následující řádek:

Poznámka
...
147.32.87.200	master	master.felk.cvut.cz	# Neexistující stroj
...

Pozn.: Jednotlivé pložky záznamu jsou odděleny tabulátory

Poznámka V tomto případě bylo použitý typu host vyloženě ilustrativní. Ve skutečnosti je pro vygenerování správného souboru /etc/hosts toho třeba zkombinovat víc - využít podmínky, napsat výchozí šablonu, atd. K tomu už je ovšem vhodnější vytvořit první samostatný modul.

Přehled použitelných typů

Šablony

Pro jednoduché konfigurační soubory lze využít funkci inline_template., která interpretuje jako obsah šablony textový řetězec

Pro rozsáhlejší konfigurační soubory je výhodnější použít šablonu uloženou v samostatném souboru. K jejímu načtení se použije funkce template.

Poznámka
class basic {
    file {"/etc/hosts":
        content => template("hosts.erb"),
    }
}

Pokud je uveden pouze název šablony, pak tato funkce hledá šablonu automaticky v adresáři /etc/puppet/templates. V případě že je šablona součástí modulu, musí modul kromě adresáře manifests obsahovat také adresář templates, do kterého je uložena. Zápis pak vypadá takto:

Poznámka
class basic {
    file {"/etc/hosts":
        content => template("hosts/hosts.erb"),
    }
}


Není nutné hlídat správnost cesty k souboru a jeho obsah jako šablonu zpracuje klient až na straně nodu. Takže na straně stroje master není třeba nic víc, než v manifestu uvést jakou má vzít šablonu.


Obsah šablony hosts.erb je pak následující:

Poznámka
127.0.0.1 localhost localhost.localdomain
<%= ipaddress -%>	<%= hostname -%>	<%= fqdn %>
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters


I když šablony pracují s proměnnými a umožňují používat funkce a jiné věci, nejsou stejným typem souboru jako ty, které se používají pro sestavení manifestu a které zpracovává master na straně serveru. Proto se také odlišují příponou '.erb' ač při jejich zpracování na příponě vůbec nezáleží.

Šablony umožňují vkládat mezi tagy '<% %>' kód v Ruby - jazyce, ve kterém je naprogramován celý Puppet. O jeho interpretaci na straně nodu se pak stará klient, který si šablonu stáhne. V šablonách lze využívat všech možností objektového programování, ale na většinu věcí postačí využít podmínek, smyček a proměnných.

Rozdíly v použití proměnných oproti Puppetu

  • U proměnných v šblonách se neuvádí počáteční znak '$' (string)
  • "Vytištění" proměnné se zajistí, když se umístí za počáteční tag znak '=' (rovnítko) '<%= %>'
  • Nemá-li dojít k odřádkování jednotlivých bloků kódu, lze potlačit konec řádku tím, že se před uzavírací tag umístí znak '-' (mínus) '<%= promenna -%><%= dalsi_promenna -%>'

Použití smyčky v šabloně

Kód manifestu, ve kterém se nastaví obsah proměnné $servers (pole)

Poznámka
class basic {
    $servers = [ "10.0.0.1      nod-1",
                 "10.0.0.2      nod-2",
                 "10.0.0.3      nod-3", ]
    file {"/etc/hosts":
        content => template("hosts.erb"),
    }
}

Obsah šablony hosts.erb, ve které se na straně klienta přes smyčku zpracuje obsah proměnné $servers

Poznámka
127.0.0.1 localhost localhost.localdomain
<%= ipaddress -%> 
<%= hostname -%> 
<%= fqdn %>
<% servers.each do | server | -%>
<%= server %>
<% end -%>
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters

A ukázka obsahu výsledného souboru /etc/hosts

Poznámka
127.0.0.1 localhost localhost.localdomain
147.32.87.200 master master.felk.cvut.cz
10.0.0.1      nod-1
10.0.0.2      nod-2
10.0.0.3      nod-3
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters

Kód v šabloně i manifestu lze pochopitelně dále vypilovat, ale to už je mimo rámec tohoto seznámení se šablonami.



Metaparametry

Metaparametry jsou speciální parametry, jimiž lze v rámci manifestu řešit vzájemné závislosti zdrojů a případně také ovlivnit přístup agenta na klientské straně ke zdroji v manifestu.


Jak je používat, bude nejlépe patrné z následujícího příkladu.

Administrace uživatelů přes puppet


Moduly

V kapitole věnované seznámení se strukturou manifestu bylo v odstavci o třídách uvedeno několik ukázkových příkladů vytvoření a implementace třídy. I když třídy mohou být součástí hlavního manifestu, je to z praktického hlediska nesmysl, protože by se stal záhy nepřehledný. Proto se implementace tříd, deklarovaných v hlavním manifestu, udržují odděleně v takzvaných modulech. Puppet má v sobě integrovaný režim pro práci s moduly, proto by každý modul by měl být v maximální míře univerzální, tak aby jej bylo možné distribuovat a sdílet. (Viz Práce s moduly).


  • Specifické manifesty soustřeďte do samostatně udržovaného modulu
  • A parametr, kterým lze na ně odkazovat, předávejte při deklaraci třídy jako její atribut.

Moduly

V deklaraci nodu se třída implementovaná v modulu deklaruje přes direktivu include stejným způsobem, jako kdyby byla součástí výchozího manifestu.

Nenajde-li Puppet v režimu master, který sestavuje katalog, třídu ve výchozím manifestu, předpokládá její výskyt ve stejnojmenném modulu.

Ve té nejprostší podobě tak modul vypadá jako adresář, v úložišti modulů na stroji kde je master, se stejným názvem, jako má použitá třída. Ten obsahuje podadresář manifests se souborem init.pp, ve kterém je deklarovaná.

init.pp

Je výchozí soubor modulu, ve kterém je deklarovaná třída a s implementovanými typy, které se pak budou zpracovávat na straně agenta.

V rámci modulu můžeme tvořit další podtřídy, které lze rovněž deklarovat v souboru init.pp, nebo v dalších souborech v rámci adresáře manifest. Každý z nich musí mít název podtřídy a příponu .pp.

Následující ukázkový kód demonstruje deklaraci třídy "hosts" ve stejnojmenném modulu, která si přes direktivu include natahuje ze souboru s názvem config.pp podtřídu "hosts::config". Před implementací kódu této podtřídy bude aplikován typ file, přes který budeme zakládat na straně agenta soubor /etc/hosts.

Obsah souboru init.pp je tedy prozatím následující:

Poznámka
class hosts {
	file {"/etc/hosts":
		content => template("obsah_pro_hosts"),
	}
	include hosts::config
}

Obsahem dalšího souboru s názvem config.pp bude podtřída modulu "hosts" - "hosts::config", která bude obsahovat typ host, přes který lze spravovat jednotlivé záznamy v souboru /etc/hosts. V ukázkovém příkladu přidává pouze jeden záznam a to nastavení jména pro IP adresu stroje master:

Poznámka
class hosts::config {
	host {"master":
		ip => '147.32.87.200',
		name => 'master',
		comment => "Puppetmaster",
		host_aliases => "master.felk.cvut.cz",
		ensure => present,
	}
}

Podtřídy

V adresáři manifests mohou být další podadresáře. Puppet pak automaticky chápe soubory v nich umístěné jako podtřídy.

Aby bylo možné k nim uvést dokumentaci, je třeba do nich přidat soubor init.pp, a v něm podtřídu deklarovat jako obvykle, nebo lze dokumentaci podtřídy (podadresáře) a její deklaraci umístit do výchozího init.pp celého modulu

Úložiště modulů

Puppet může mít prostřednictvím proměnné $modulepath nastaveno více než jedno úložiště modulů. Na prvním místě je, coby jako výchozí úložiště, adresář modulů příslušného prostředí. Za ním, odděleny dvojtečkou, mohou být uvedeny další cesty. Nepracuje-li agent v odděleném prostředí, jsou moduly obvykle umístěny v adresáři /etc/puppet/modules.

user@stroj~$ sudo puppet agent --configprint modulepath
/etc/puppet/environments/testing/modules:/etc/puppet/modules:/usr/share/puppet/modules

Třídu "basic" z ukázkové deklarace nodu by tedy master postupně hledal v souborech:

  1. /etc/puppet/environments/testing/modules/basic/manifests/init.pp
  2. /etc/puppet/modules/basic/manifests/init.pp
  3. /usr/share/puppet/modules/basic/manifests/init.pp

Pro další proces zpracování manifestu akceptuje master vždy pouze první deklaraci třídy, na kterou narazí.

Pokud ji nikde nenajde, skončí proces generování manifestu chybovým oznámením.

Struktura modulu

Kromě povinného adresáře manifests se mohou v kořeni modulu vyskytnout i další soubory a adresáře. Z hlediska sestavení manifestu jsou významné především tyto:

  • files pro uložení souborů
  • templates pro uložení šablon
  • lib uživatelské pluginy; .rb skripty, které nejsou součástí instalace agenta
  • facts.d spustitelné soubory pro zístávání externích fakt
  • tests pro ilustrační soubory s deklarací tříd a metod implementovaných v modulu
  • spec soubory pro testování pluginů


files

Je adresář ve kterém jsou uloženy soubory a adresáře, které se mají distribuovat tak jak jsou (ssh klíče, výchozí konfigurační soubory aj.). Agent k nim přistupuje přes filebucket v rámci jmenného prostoru příslušného modulu. Není tak nutné si hlídat absolutní cesty v rámci souborového systému stroje master.

Poznámka
 file {"/etc/hosts":
         source => "puppet:///modules/hosts/hosts_default",
 }

templates

Je adresář, do kterého se ukládají šablony. Šablony jsou soubory s příponou .erb, jejichž obsah může být je během zpracování modifikován díky vloženým kouskům interpretovaného kódu programovaného v ruby.

Poznámka
 file {"cesta_k_souboru/soubor.txt":
         content => template("hosts/hosts_sablona.erb",
 }

lib

Pomocí pluginů lze do modulu integrovat funkce, typy a fakta, co nejsou standardní součástí Puppetu. Pluginy jsou soubory, uložené v podadresářové struktuře adresáře lib. Více viz v kapitole Puppet - Fakta a pluginy.

facter

Skripty s příponou .rb v tomto adresáři, dovolují získat a nastavit během zpracování manifestu další fakta se kterými lze pracovat.

augeas

lenses
Do tohoto adresáře lze umístit parsery konfiguračních souborů (lens), které nejsou standardní součástí instalačního balíku augeas-lenses. Více k augeasu viz kapitola Augeas - nástroj pro práci s konfiguračními nástroji
Poznámka Podpora pro Augeas je od Puppetu verze 2.7.18

puppet

parser/functions
Sem se umístí skript s příponou .rb, který umožní přidat další funkci využitelnou při zpracování manifestu.
provider/<type>
Skripty s příponou .rb, které dovolí rozšířit možnosti některého ze stávajících typů, jsou umístěny do podadresářů, s názvem odpovédajícího typu. Kupř. soubor lib/puppet/provider/package/source.rb bude obsahovat kód, kterým lze přidat další parametry k typu package
type
Lze také ke stávajícím typům přidat další typ, skriptem s příponou .rb umístěným sem.

facts.d

Do tohoto adresáře lze umístit skripty a binární soubory, jejichž výstupem lze nastavit další využitelná fakta. Pozor, tyto soubory musí být spustitelné agentem!.

tests

spec

Dokumentování modulů

Dokumentace ke třídám a metodám v modulu se tvoří úplně stejným způsobem, jako když se dokumentuje kód manifestu.

Kromě podrobné dokumentace jednotlivých metod a tříd však můžeme mít zpracovanou také globální dokumentaci modulu v souboru README. Ten se umisťuje do kořene modulu a může mít případně také příponu .rdoc, nebo .md podle použité formátovací konvence.

README

Soubor README se nachází v kořeni modulu a pokud nemá příponu .rdoc, nebo .md, která by specifikovala použitou formátovací konvence, tak se předpokládá, že je obsah formátovaný pomocí rdoc. Při generování dokumentace do HTML se jeho obsah sloučí s dokumentací veřejných metod, které jsou dokumentovány v kódu, takže lze na ně odkazovat skrze hyperlinky[2].

README.rdoc
musí mít obsah formátovaný jako rdoc, stejně jako dokumentace v kódu. Pouze s tím rozdílem, že nejde interpretované komentáře, tudíž řádky nezačínají znakem #
README.md
musí mít obsah formátovaný jako markdown. V tomto případě však vygenerovaná dokumentace nebude zkombinována s dokumentací k veřejným metodám.

Práce s moduly

Jak už bylo zmíněno hned v úvodu této kapitoly, kód v modulech by měl být v maximální míře obecný a univerzálně použitelný. Napsat takový modul však není nic jednoduchého. Proto firma Puppet Labs, která vývoj Puppetu zaštiťuje, od verze 2.7.10 nabízí jeho uživatelům možnost vytvořené moduly sdílet prostřednictvím úložiště na serveru Puppet Forge.

Nástroj pro práci s moduly, který umí také pracovat s tímto úložištěm, je v Puppetu integrován. takže vyhledávat vhodné moduly a instalovat je do lokálního úložiště modulů lze rovnou z příkazové řádky.

Vyhledání a instalace modulu z úložiště na Puppet Forge

Dříve, než začneme psát vlastní modul bychom se tedy měli poohlédnout, zda-li již pro to co potřebujeme někdo nějaký modul nevytvořil.

Následující příklad demonstruje vyhledání modulu pro instalaci a konfiguraci poštovního serveru exim4

Poznámka
root@master~# puppet module search exim
Notice: Searching https://forgeapi.puppetlabs.com ...
NAME                DESCRIPTION                     AUTHOR        KEYWORDS      
example42-exim      Puppet module for exim          @example42    exim mail     
joejulian-exim      Manages Exim                    @joejulian    CentOS exim   
akumria-nullmailer  Install and configure nullm...  @akumria      mail mta exim

Pokud se rozhodneme vyzkoušet kupř. modul od uživatele example42, nainstalujeme do svého lokálního úložiště modulů modul example42-exim. Instalace modulu není v podstatě nic jiného, než stažení zabaleného archívu z webu a jeho rozbalení do úložiště modulů /etc/puppet/modules příslušného prostředí.

Poznámka
root@master~# puppet module install -i /etc/puppet/modules --verbose example42-exim
Notice: Preparing to install into /etc/puppet/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Info: Resolving dependencies ...
Info: Preparing to install ...
Notice: Installing -- do not interrupt ...
/etc/puppet/modules
└─┬ example42-exim (v2.0.13)
  └── example42-puppi (v2.1.9)

Distribuce vlastního modulu

Vytvořit vlastní instalační balíček modulu není nic těžkého.

V podstatě stačí do kořene modulu doplnit soubor metadata.json, ve kterém jsou uloženy základní informace o modulu:

  • jak se jmenuje
  • kdo ho vytvořil
  • jaké má číslo verze
  • co vlastně obsahuje
  • a případně na jakých dalších modulech závisí
Poznámka Starší verze Puppetu místo něj používaly soubor s názvem Modulefile

Modulefile

metadata.json

Soubor s informacemi o modulu pro práci s moduly v rámci Puppetu (viz níže).

Zabalení modulu

Poznámka
root@master~# puppet module build /etc/puppet/modules/admins
Notice: Building /etc/puppet/modules/admins for release
Module built: /etc/puppet/modules/admins/pkg/want-admins-0.1.1.tar.gz

Instalace modulu z lokálního tarballu

Instalaci z lokálního tarballu je třeba provádět s parametrem --ignore-dependencies, protože pokud by ve svých závislostech odkazoval na modul který není součástí Puppet Forge, skončila by instalace oznámením, že balík nelze nainstalovat pro nesplněné závislosti.

Poznámka
root@master~# puppet module install --environment testing ~/want-admins-0.1.1.tar.gz --ignore-dependencies --force
Notice: Preparing to install into /etc/puppet/environments/testing/modules ...
Notice: Installing -- do not interrupt ...
/etc/puppet/environments/testing/modules
└── want-admins (v0.1.1)

Bez parametru --force lze modul instalovat pouze pokud neexistuje.

Poznámka
root@master~# puppet module install --environment testing ~/want-admins-0.1.1.tar.gz --ignore-dependencies
Notice: Preparing to install into /etc/puppet/environments/testing/modules ...
Error: Could not install module 'want-admins' (v0.1.1)
  Installation would overwrite /etc/puppet/environments/testing/modules/admins
    Use `puppet module install --force` to install this module anyway

S parametrem --force instalace z balíku nahradí stávající obsah modulu.

Přehled nainstalovaných modulů

K výpisu modulů se používá příkaz list. To postačí, pokud se nepoužívá jiné než výchozí prostředí. Jinak se musí atributem --environment upřesnit výchozí prostředí.

Poznámka
root@master~# puppet module list --environment testing
/etc/puppet/environments/testing/modules
├── apache2 (???)
...
└── want-vim (v0.1.0)
/etc/puppet/modules
├── puppetlabs-apt (v1.2.0)
...

Z následujícího ukázkového výpisu modulů lze vyčíst že..

  • Modul apache2 zatím není nijak podchycen, protože mu chybí číslo verze (chybí soubor metadata.json. Podle tohoto čísla se udržuje přehled o závislostech modulů, proto při každé úpravě modulu, která může mít vliv na jeho implementaci vy mělo být číslo verze navýšeno.
  • Modul want-vim, je již upraven zcela v souladu s pravidly. Je to lokálně nainstalovaný modul, u kterého bylo výchozí číslo verze v0.1.0 bylo navýšeno po drobné úpravě
  • Modul puppetlabs-apt je ale instalován z repozitáře Puppet Forge. Vyskytne-li se v takovém modulu nějaká chyba, měl by být především informován tvůrce modulu (v tomto případě puppetlabs), aby se mohl postarat o nápravu. Vydá-li pak aktualizovanou verzi modulu, je třeba provést aktualizaci.

Aktualizace modulu

K aktualizaci modulů se používá příkaz upgrade

Poznámka
root@master~# puppet module upgrade --environment testing puppetlabs-apt --modulepath /etc/puppet/modules
Notice: Preparing to upgrade 'puppetlabs-apt' ...
Notice: Found 'puppetlabs-apt' (v1.2.0) in /etc/puppet/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Upgrading -- do not interrupt ...
/etc/puppet/modules
└── puppetlabs-apt (v1.2.0 -> v1.5.0)
Upozornění Pokud je modul nainstalován do jiné cesty, než která přísluší prostředí - stejně jako v tomto ukázkovém případě - skončí aktualizace cbybou. U takového modulu musí být uvedeno prostřednictvím atributu --modulepath, ve které lokaci se zdrojové kódy modulu skutečně nalézají.

Odebrání modulu

Vygenerování struktury modulu

git (PUPPET) :~# puppet module generate --environment production want-lvm2
We need to create a metadata.json file for this module.  Please answer the
following questions; if the question is not applicable to this module, feel free
to leave it blank.

Puppet uses Semantic Versioning (semver.org) to version modules.
What version is this module?  [0.1.0]
--> 

Who wrote this module?  [want]
--> 

What license does this module code fall under?  [Apache 2.0]
--> GPLv3

How would you describe this module in a single sentence?
--> Konfigurace LVM volumes

Where is this module's source code repository?
--> 

Where can others go to learn more about this module?
--> 

Where can others go to file issues about this module?
--> 

----------------------------------------
{
  "name": "want-lvm2",
  "version": "0.1.0",
  "author": "want",
  "summary": "Konfigurace LVM volumes",
  "license": "GPLv3",
  "source": "",
  "project_page": null,
  "issues_url": null,
  "dependencies": [
    {"name":"puppetlabs-stdlib","version_requirement":">= 1.0.0"}
  ]
}
----------------------------------------

About to generate this metadata; continue? [n/Y]
--> y

Notice: Generating module at /root/want-lvm2...
Notice: Populating templates...
Finished; module generated in want-lvm2.
want-lvm2/manifests
want-lvm2/manifests/init.pp
want-lvm2/spec
want-lvm2/spec/classes
want-lvm2/spec/classes/init_spec.rb
want-lvm2/spec/spec_helper.rb
want-lvm2/tests
want-lvm2/tests/init.pp
want-lvm2/Gemfile
want-lvm2/Rakefile
want-lvm2/README.md
want-lvm2/metadata.json
  1. Tento manuál začal vznikat v době vydání verze 2.7.18
  2. To ovšem neplatí pokud budou použity k formátování dokumentace značky pro Markdown (soubor README.md)


Příklady

Puppet (příklady