Error 400 on SERVER: Could not find class “foo” for “node” on “node”

Alweer een Puppetprobleem. Opeens zegt de puppet-agent dat hij een bepaalde module niet kan vinden op de master. Maar, zoals in alle slechte verhalen, de module was er wel. En ze stond op de juiste plaats.

Zowat alles werd onderzocht. De module stond er, was correct, vertoonde geen syntaxfouten; de server had rechten om te lezen en uit te voeren; kortom, er was geen enkele reden waarom het niet zou werken.

En toch

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find class

Frustrerend.

Na nog wat extra google-fu werd de oplossing gevonden in een ondergesneeuwd antwoord op deze vraag. Was de metadata.json wel correct? En jawel. Ik had de parameters “requirements” en “dependencies” omgedraaid. requirements verwijst naar de verwachte puppetversie en is niet verplicht. De puppetmodules die nodig zijn voor de module staan in dependencies. En helaas bleek ik die te hebben omgewisseld.

Op zich geen probleem (afhankelijkheden worden niet gecontroleerd in onze setup), maar ik had enkel “requirements” en niet “dependencies“. En dependencies is verplicht, en als een verplichte parameter ontbreekt, dan weigert puppet dienst. Met een wel heel verwarrende foutmelding tot gevolg.

Puppetmodules in RubyMine

In RubyMine, een uitstekende IDE uit de Jetbrainsstal, kan je Puppetmodules ontwikkelen (de taal is ondersteund), maar je moet enkele dingen in het achterhoofd houden.

Zo eentje heb ik vandaag ontdekt. Opdat RubyMine automatisch de naam van variabelen, functies en klassen uit jouw module zou aanvullen, moet je ervoor zorgen dat ze op één of andere manier door heeft dat je een module aan het ontwikkelen bent.

De oplossing is eenvoudig en elegant: voeg een metadata.json-bestand toe en zorg ervoor dat de structuur van de module overeen komt met de documentatie.

Een kleine moeite, een wereld van verschil.

hiera-eyaml – caveat emptor

Ik gebruik Puppet voor mijn persoonlijk serverpark, en ben daar best tevreden over. Maar af en toe …

Zoals nu dus. In het kader van een herstructurering wordt de Puppetmaster gemigreerd van een VPS naar een fysieke server. Wanneer ik zeg gemigreerd, bedoel ik eigenlijk opnieuw opgezet, met een aantal verbeteringen, zoals daar zijn verschillende environments en r10k voor de synchronisatie van repositories en modules.

Omdat alles in git zit (uiteraard) en ik een beetje paranoïde ben, versleutel ik mijn wachtwoorden en SSH-sleutels (opgeslagen in Hiera) met hiera-eyaml.

De gem (Ruby …) was mooi geïnstalleerd, en mijn hiera.yaml (geconfigureerd per environment) leek in orde.

:hierarchy:
 - "%{::osfamily}"
 - webservers
 - databases
 - roles
 - common
:backends:
 - eyaml
 - yaml
:yaml:
 :datadir: "/etc/puppetlabs/code/environments/%{::environment}/hieradata"
:eyaml:
 :datadir: "/etc/puppetlabs/code/environments/%{::environment}/hieradata"
 :pkcs7_private_key: "/etc/puppetlabs/puppet/keys/private_key.pkcs7.pem"
 :pkcs7_public_key: "/etc/puppetlabs/puppet/keys/public_key.pkcs7.pem"

Maar … Het werkte toch niet (anders was er nu geen blogpost). Na een (vruchteloze) speurtocht doorheen /etc om alle mogelijke hiera.yaml-bestanden die de Puppetserver (foutief) zou kunnen inladen te verwijderen, bleef dezelfde foutmelding terugkomen.

Sep 1 21:14:40 stock puppet-agent[6330]: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Function lookup() did not find a value for the name 'account_data' on node s1.admin.dc.nidavellir.be

Maar dan, in de krochten van de README (…), bleek dat het niet voldoende was om de gem te installeren via gem install hiera-eyaml. Neen. Dat moest gebeuren via de Puppetserver:

/opt/puppetlabs/bin/puppetserver gem install hiera-eyaml

En jawel …

Sep 2 12:32:53 stock puppet-agent[23914]: Applied catalog in 152.87 seconds

Hoera!

Puppet: invalid byte sequence in US-ASCII

Puppet probeert een bestand te parsen, denkt dat het ASCII is, maar dat is het niet en faalt dus. Een é gebruiken doe je niet ongestraft.

Dit is geen probleem met Puppet, maar met de locale die ingesteld staat op het systeem. Op zich eenvoudig op te lossen, ware het niet dat het “systeem” in kwestie een docker container is, gebaseerd op Red Hat Enterprise Linux 7.3.

Om een lang verhaal kort te maken, je moet in de Dockerfile de locale-environment variables toevoegen (het uitvoeren van localegen is op RHEL 7.3 niet nodig).

ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LANGUAGE en_US:en

En zo staat de locale ingesteld op UTF-8, waardoor de puppet parser dit overneemt en de foutmelding magisch verdwijnt.

Hoera!

DNS @ OSX

Blijkbaar gebruikt OS X zowel udp als tcp om met de DNS-server te verbinden. Maar Linux gebruikt enkel tcp. Zo is het niet moeilijk dat het voor mij wel werkt en voor anderen niet.

Ook. In Puppet doet:

firewall { '609 DNS ACCEPT':
        proto => ['tcp', 'udp']

niet wat je zou verwachten.

Ask me how I know.