Aiemmassa blogikirjoituksessa käsittelin custom faktojen luontia dynaamisesti. Tällä kertaa käsittelemme ulkoisten faktojen ("external facts") perusteita. Puppetlabsin oma dokumentaatio aiheesta on varsin laadukasta, kunhan sen vain malttaa lukea ajatuksen kanssa (toisin kuin allekirjoittanut).
Ulkoisilla faktoilla tarkoitetaan faktoja, joiden arvon Facter päättelee niiden tulosteesta ja joita ei tyypillisesti ole kirjoitettu Rubyllä vaan esim. Bashilla, Pythonilla tai PowerShellillä. Ne toimivat muutoin kuin "oikeat" faktat, mutta niissä ei voida viitata muihin faktoihin, eikä niitä voi rajata ("confine") toimimaan vain jossain käyttöjärjestelmässä.
Ulkoiset faktat kannattaa lisätä jonkin Puppet-moduulin facts.d -hakemistoon, jolloin Puppet löytää ne automaattisesti. Alla luodaan muutama ulkoinen, yksinkertainen Powershell-fakta, jotka lisätään moduuliin psfacts:
> New-Item -Type directory psfactsfacts.d
Sitten luodaan uusi tiedosto, psfactsfacts.dfileversions.ps1, tekstieditorilla (esim. notepad++):
$openvpn_version = (Get-Item 'C:Program FilesOpenVPNbinopenvpn.exe').VersionInfo.ProductVersion $openssl_version = (Get-Item 'C:Program FilesOpenVPNbinlibssl-1_1-x64.dll').VersionInfo.ProductVersion Write-Output "openvpn_version=$openvpn_version" Write-Output "openssl_version=$openssl_version"
Fakta kaivaa ensin esiin Powershellillä OpenVPN:n (exe) ja OpenSSL:n (dll) versiot. Varsinaiset faktat luodaan tulostamalla ne Write-Output CmdLetillä muodossa
key=value
Huomaa, että samassa tiedostossa voidaan luoda useita faktoja: facteria kiinnostaa vain se, että skripti tulostaa jotakin tarkalleen yllä olevassa muodossa. Huomaa, että faktan nimen ja faktan arvon välillä ei saa olla välilyöntejä.
Faktaa on helpointa testata suoraan Powershellistä facterilla:
PS> facter.bat --external-dir psfactsfacts.d openvpn_version 2.4.5.0 PS> facter.bat --external-dir psfactsfacts.d openssl_version 1.1.0f
Aivan samalla tavalla voidaan luoda external faktoja UNIX:ssa:
#!/bin/sh echo "fact=value" echo "anotherfact=value"
UNIX:in tapauksessa pitää muistaa määrittää komentotulkki (yllä /bin/sh) ja sallia tiedoston käynnistäminen (chmod +x <filename>).
Staattisten faktojen kirjoittaminen on varsin helppoa melko vähäisinkin Ruby-taidoin. Alla esimerkki faktasta, joka palauttaa true tai false riippuen siitä, onko noodilla /boot-osiota:
Facter.add(:has_bootfs) do setcode do if Facter.value(:mountpoints)['/boot'].nil? false else true end end end
Kuten yltä näkyy, itse tieto löytyi jo valmiiksi Facterin "mountpoints"-faktan sisältä: yllä sen sisältöä vain muunnettiin erilliseksi, helposti käsiteltäväksi faktaksi visualisointia ja skriptausta helpottamaan.
Mountpoints-fakta sisältää myös paljon muuta kiinnostaa tietoa, kuten sen, miten suuri osio on ja paljonko siellä on tilaa vapaana. Jos näistäkin tiedoista halutaan luoda samaan tapaan erilliset faktat, voidaan ne helposti luoda dynaamisesti:
if Facter.value(:has_bootfs) facts = [ 'size','available'] facts.each do |fact| Facter.add("bootfs_#{fact}") do setcode do Facter.value(:mountpoints)['/boot'][fact] end end end end
Yllä oleva koodi siis luo kaksi uutta faktaa mutta vain jos /boot-osio on olemassa:
Näitä faktoja voidaan käyttää normaaliin tapaan:
$ facter -p has_bootfs true $ facter -p bootfs_size 235.32 MiB $ facter -p bootfs_available 111.28 MiB
Vaikka yllä olevassa esimerkissä ei varsinaisesti luoda mitään uutta dataa, voi samalla strategialla muodostaa räätälöityjä faktoja dynaamisesta sisällöstä. Alla luodaan erillinen fakta ("user_<username>_is_present") jokaisesta *NIX-järjestelmässä olevasta käyttäjästä pois lukien järjestelmäkäyttäjät:
require 'etc' Etc.passwd do |entry| # Normal users have IDs in this range in /etc/login.defs if entry.uid >= 1000 and entry.uid <= 60000 Facter.add("user_#{entry.name}_is_present") do setcode do true end end end end
Näiden dynaamisesti luotujen faktojen käyttö on helppoa:
$ facter -p user_john_is_present true $ facter -p user_jack_is_present $ facter -p user_jane_is_present true
Ainoa rajoitus on se, että datasta, jota ei ole olemassa, ei voida tietenkään luoda faktaa. Esimerkiksi yllä fakta käyttäjästä "jack", jota ei ole olemassa, saa tyhjän arvon (undef/nil) sen sijaan, että se palauttaisi totuusarvon false. Tällä ei Puppet-koodin tai faktojen visualisoinnin kannalta ole kuitenkaan suurta merkitystä.