Vor ungefähr einem Monat hatte ich die Wahl: ob ich das Modul für Puppet "auf den Tisch" (dh für die interne Infrastruktur) schreiben oder universell machen, die Quelle öffnen und auf Puppet Forge veröffentlichen möchte . Natürlich wäre es schneller und einfacher, schnell 2-3 Noten für sich selbst zu skizzieren und sich zu beruhigen, aber die Erfahrungen, die bei der Veröffentlichung des Moduls gesammelt wurden, sind wertvoll und ich möchte sie teilen. In RuNet gibt es keine Informationen zur Verwendung des Puppenentwicklungskits (im Folgenden: PDK ). Sie können dies also als eine Art Tutorial betrachten.
Worum geht es in dem Artikel?
Bei der Entwicklung eines Moduls (oder besser gesagt zweier) habe ich PDK entdeckt, das sowohl die Entwicklung als auch die Wartung von Modulen erheblich erleichtert. Nämlich:
- Formatieren Sie
metadata.json
beim letzten Update automatisch - Konfigurationsgenerierung für verschiedene CI-Systeme, die Folgendes tun können:
- Rubincode mit Rubocop Linter prüfen
- Unit-Tests ausführen
- Unter bestimmten Bedingungen - automatisches Ausfüllen des Arbeitscodes für Puppenschmieden
- Generieren von tagbasierter Dokumentation in Kommentaren mithilfe von Yard
- Platte
[PDK]
für das Modul auf Puppenschmiede. Eine Kleinigkeit, aber schön!
Alle interessiert Ich bitte um eine Katze!
Als Beispiele
Wenn Sie sehen und fühlen möchten, was während des Lesevorgangs gemeint ist, können Sie eines der beiden (oder beide) genannten Module öffnen : clickhouse und xmlsimple . Beide wurden mit dem PDK und anderen im Artikel beschriebenen Tools entwickelt.
Inhalt
Was ist PDK?
Aus der offiziellen Dokumentation:
Erstellen Sie ein vollständiges Modul mit Klassen, definierten Typen und Aufgaben und testen und validieren Sie Ihre Arbeit unterwegs. PDK bietet eine vollständige Modulstruktur, Vorlagen für Klassen, definierte Typen und Aufgaben sowie eine Testinfrastruktur. Sie können Ihr Modul anhand verschiedener Betriebssysteme und mehrerer Puppet-Versionen validieren und testen.
In meiner kostenlosen Übersetzung:
Ermöglicht das Erstellen eines vollständigen Moduls mit Klassen, Typen, Aufgaben und Tests, um den Betrieb des Moduls zu überprüfen. PDK bietet eine vollständige Struktur und Vorlagen für alle oben genannten. Mit diesem Tool können Sie die Funktion des Moduls mit verschiedenen Versionen von Puppet sowie in verschiedenen Betriebssystemen überprüfen.
Hört sich gut an? So ist es wirklich. Bis zu dem Zeitpunkt, als ich mit der Arbeit an dem Modul begann, das sofort für Open Source geschrieben werden sollte, ahnte ich dieses Tool nicht und beabsichtige nun, die gesamte interne Infrastruktur für die Verwendung des PDK zu übertragen.
Ich werde beschreiben, wie es zu setzen ist und welche Werkzeuge und Befehle es enthält.
Installation
Die offizielle Installationsseite . Über diesen Link finden Sie fast garantiert den richtigen Weg, um PDK auf Ihrem Host zu installieren. Wenn Sie aus irgendeinem Grund kein Glück haben und Ihr Betriebssystem nicht vorhanden ist, gibt es immer einen Kreisverkehr in der Form:
gem install pdk
In der Tat ist PDK nur ein Juwel, und es ist so eingestellt.
PDK-Inhalt
Im Allgemeinen ist PDK nichts anderes als eine Reihe von Edelsteinen, um die Modulentwicklung zu erleichtern. Es enthält die folgenden Tools:
Dienstprogramm | Beschreibung |
---|
metadata-json-lint | Überprüft metadata.json auf passende Puppenstil-Anleitungen |
pdk | Ein Tool zum Generieren und Testen von Modulen und deren Inhalten (Klassen, Typen usw.) über die Befehlszeile |
Marionettenfussel | Überprüft den Puppencode auf Puppet Language Style Guides |
Puppensyntax | Überprüfen Sie die Syntax des Manifests |
Puppetlabs_spec_helper | Bietet Rake-Klassen, Methoden und Aufgaben für Spezifikationstests von Puppet-Code |
rspec-Marionette | Testet das Verhalten von Puppen beim Kompilieren von Manifesten im Ressourcenverzeichnis (?) |
rspec-Marionetten-Fakten | Ermöglicht das Ausführen von rspec-puppet mit benutzerdefinierten Puppet-Fakten |
Erstellen Sie ein Modul
PDK installiert, jetzt können Sie herumspielen. Der einfachste pdk help
zeigt die verfügbaren Befehle an. Angenommen, wir befinden uns in dem Ordner, in dem Sie alle anderen Module haben. Dann erstellen wir eine neue:
$ pdk new module --template-url=https://github.com/puppetlabs/pdk-templates.git *** We need to create the metadata.json file for this module, so we're going to ask you 5 questions. *** [Q 1/5] If you have a name for your module, add it here. --> dummy [Q 2/5] If you have a Puppet Forge username, add it here. --> felixoid [Q 3/5] Who wrote this module? --> Mikhail f. Shiryaev [Q 4/5] What license does this module code fall under? --> MIT [Q 5/5] What operating systems does this module support? --> RedHat based Linux, Debian based Linux, Windows Metadata will be generated based on this information, continue? Yes pdk (INFO): Module 'dummy' generated at path '/tmp/dummy', from template 'https://github.com/puppetlabs/pdk-templates.git'.
Das Dienstprogramm stellt Fragen zum Ausfüllen der Datei metadata.json, und die Ausgabe enthält genau das, was angezeigt wird: das Modul und die Zusatzdateien, die aus Vorlagen aus dem Git kompiliert wurden.
Eine kleine Bemerkung - Temlites ändern sich ziemlich oft, einschließlich einiger kritischer Fehler, die kürzlich behoben wurden. Daher ist es besser, nicht die Standardeinstellungen des installierten PDK zu verwenden, sondern die neueste Version. Es --template-url
, es gibt eine Kehrseite: Wenn PDK das Argument --template-url
, fügt es diesen Parameter der ~.pdk/cache/answers.json
und versucht, pdk
an den Verzögerungen bei der weiteren Ausführung eines der pdk
Befehle, diese herunterzuladen. Entfernen Sie diesen Parameter entweder aus answers.json
oder verwenden Sie ihn nicht beim Erstellen eines Moduls und ändern Sie ihn in metadata.json
.
Lassen Sie uns die weiteren Schritte durchgehen, die mit dem PDK ausgeführt werden können.
neue Klasse
$ pdk new class dummy::class pdk (INFO): Creating '/tmp/dummy/manifests/class.pp' from template. pdk (INFO): Creating '/tmp/dummy/spec/classes/class_spec.rb' from template. $ cat manifests/class.pp # A description of what this class does # # @summary A short summary of the purpose of this class # # @example # include dummy::class class dummy::class { } $ cat spec/classes/class_spec.rb require 'spec_helper' describe 'dummy::class' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } it { is_expected.to compile } end end end
Dieser Befehl erstellt zwei Dateien: das Manifest selbst für die Klasse und die Spezifikationsdatei zum Testen. Ich werde später genauer auf die Tags zur Dokumentation eingehen.
neuer definierter_Typ
$ pdk new defined_type type pdk (INFO): Creating '/tmp/dummy/manifests/type.pp' from template. pdk (INFO): Creating '/tmp/dummy/spec/defines/type_spec.rb' from template.
Trotzdem: Manifest für Ressourcentyp und Spezifikationsdatei.
neuer Anbieter & Aufgabe
PDK kann auch einen neuen Anbieter oder eine neue Aufgabe erstellen, aber ich habe nicht eng mit ihnen zusammengearbeitet. Daher kann ich ehrlich sagen, dass es besser ist, dieses Thema bei Bedarf eingehender zu untersuchen.
Dokumentation mit Marionettenschnüren erstellen
Ich verstehe nicht wirklich, warum puppet strings
nicht Teil des PDK-Toolkits sind, dies ist jedoch la la. Wenn Sie während der Entwicklung Tags für den Hof korrekt platziert haben, gibt es zwei Möglichkeiten, dem Benutzer Dokumentation zur Verfügung zu stellen:
- Generieren Sie es als HTML / Markdown / JSON und platzieren Sie es neben dem Code. Dies geschieht mit dem Befehl "
puppet string generate [--format FORMAT]
, bei dem das Format weggelassen oder auf " json
/ puppet string generate [--format FORMAT]
werden kann.
- Es ist üblich, die Datei
REFERENCE.md
im Stammverzeichnis des Repositorys als Dokumentationsstandard zu haben, der mit dem puppet strings generate --format markdown
.
- Veröffentlichen Sie im Repository mit Code (vorausgesetzt, es befindet sich auf Github) Github-Seiten. Dies ist ganz einfach, Sie benötigen 3 Befehle:
Es scheint keine Magie zu sein, aber am Ausgang haben wir ein Modul mit Anweisungen. Das Plus ist, dass die Ausgabe auch dann eine Klasse / ein Typ / eine Funktion mit einer minimalen Beschreibung der Parameter mit dem Typ und dem Standardwert ist, wenn Sie beispielsweise nicht jeden der Parameter mit dem @param
Tag beschreiben. Meiner bescheidenen Meinung nach ist sogar dies besser als nichts und wird das Modul für den Einsatz attraktiver machen.
All dies kann natürlich automatisiert und als CI-Stufe hinzugefügt werden. Das wäre perfekt. Meine Hände haben noch nicht erreicht, aber es sammelt sich Staub im Rückstand. Wenn plötzlich jemand etwas zu diesem Thema zu sagen hat, bin ich dankbar. Als Gedanken: Fügen Sie mindestens einen Check hinzu, um festzustellen, ob sich REFERENCE.md nach dem Ausführen von Puppet-Strings ändert. Wenn ja, denken Sie daran, dass die Tests fehlgeschlagen sind.
Vorlagenanpassung
Die Dokumentation für Vorlagen befindet sich im Repository von pdk-templates . Kurz gesagt, alles wird mithilfe der Datei .sync.yml
im Stammverzeichnis des Moduls konfiguriert, und die Änderungen werden mit dem Befehl pdk update
. Jeder der Parameter dieser Datei ist der Name einer anderen Datei im Verzeichnis des Moduls, die auf die eine oder andere Weise geändert werden muss. Die meisten Parameter für jede der Vorlagen musste ich "per Berührung" auswählen und dabei häufig den Quellcode betrachten - durch Ausprobieren. Die Dokumentation hier bleibt manchmal weit zurück. Leider gibt es fast nichts mehr zu sagen, außer einen Link zu einem Beispiel aus Ihrem eigenen Repository zu geben.
Ich werde sehr schnell einige Parameter beschreiben, die ich mithilfe der .sync.yml
aus dem obigen Beispiel geändert habe:
Gemfile
: Zwei Gemfile
wurden als Abhängigkeiten in verschiedenen Gruppen hinzugefügt: pdk in der Entwicklungsgruppe; xml-simple in der Abhängigkeitsgruppe. Beim Starten der Tests ist die Gruppe system_tests nicht installiert, daher füge ich die Abhängigkeit einer anderen Gruppe hinzu.spec/spec_helper.rb
: Die Rauchmethode wurde geändert, der Mindestschwellenwert für die Testabdeckung wurde hinzugefügt, unterhalb dessen die Tests als fehlgeschlagen gelten..travis.yml
: Diese Datei wurde lange Zeit poliert, da sie zum Überprüfen der Codebasis und zum Laden des fertigen Moduls in Puppet-Forge verwendet wird. Änderungen:
- Benutzer und verschlüsseltes Passwort zum Ausfüllen des Moduls in Puppet-Forge. Weitere Informationen zum Einsatz von Puppet-Forge bei Travis finden Sie hier .
- Eine Testsequenz wurde erstellt → Bereitstellung mit dem Start der letzteren nur bei erfolgreichen Tests.
- Die Phase der Bereitstellung des Moduls für Puppet-Forge wurde hinzugefügt, vorausgesetzt, das CI wird über das Tag gestartet, das mit dem Zeichen "v" beginnt.
Rakefile
: Einige Ausnahmen für den Linter wurden hinzugefügt.
Verschiedene CI ausführen
Hier ist alles ganz einfach. Unmittelbar nach dem Generieren des Moduls mit dem PDK beginnt die Validierung in Appveyor, Travis und Gitlab-CI. Um die Tests auszuführen, ist alles .sync.yml
einsatzbereit. Für die .sync.yml
dieselbe .sync.yml
. Ich habe keine besonderen Vorlieben, daher werde ich nichts empfehlen. Verwenden Sie einfach das, was bequemer ist.
Bonus: Wir schreiben Unit-Tests für Klassen, Typen und Funktionen
Dieser Punkt geht weit über das Grundmaterial hinaus, das ich beschreiben wollte, aber er scheint mir sehr nützlich zu sein.
Wir haben also ein Modul mit Manifesten und eine Bibliothek, die wiederum Klassen, Typen und Funktionen enthält (wir vergessen auch nicht Aufgaben und Anbieter, aber ich habe kein Fachwissen in diesem Teil). Da jeder Code zum Ändern vorhanden ist, wäre es natürlich schön, ihn mit Tests zu überlagern, um zwei Dinge sicherzustellen:
- Änderungen unterbrechen nicht das aktuelle Verhalten (oder Verhaltensänderungen bei Tests)
- Ihre Manifeste tun genau das, was Sie erwarten, und nutzen alle Ressourcen, die Sie erwarten.
Puppetlabs bietet eine Erweiterung für das Rspec-Framework Puppet-Rspec . Links zur Dokumentation zum Testen von Klassen , Typen und Funktionen . Seien Sie nicht zu faul, um genau hinzuschauen, es gibt andere Abschnitte.
Es ist ganz einfach, es zu benutzen, ohne Rubin zu kennen. Wenn Klassen oder Typen wie oben gezeigt mit pdk new <thing>
, ist auch die Datei *_spec.rb
bereits vorhanden. Nehmen wir also an, wir haben eine dummy::class
. Zum Testen muss eine Datei spec/classes/class_spec.rb
mit den folgenden Inhalten erstellt werden:
require 'spec_helper' describe 'dummy::class' do on_supported_os.each do |os, os_facts| context "on #{os}" do let(:facts) { os_facts } it { is_expected.to compile } end end end
Sie können dies überprüfen, indem Sie die pdk test unit
im Stammverzeichnis des Moduls pdk test unit
.
Das ist fast alles was wir brauchen. Nun bleibt es, class_spec.rb
erforderlichen is_expected
mit den entsprechenden Bedingungen zu ergänzen. Um beispielsweise zu überprüfen, ob die Klasse die Ressource file {'/file/path': }
mit bestimmten Parametern enthält, können Sie Folgendes tun:
it do is_expected.to contain_file('/file/path').with( 'ensure' => 'file', 'mode' => '0644' ) end
Sie können Klassenparameter mit let(:params) { {'param1' => 'value'} }
Es ist möglich, Tests unter verschiedenen Eingabebedingungen durchzuführen, indem Sie sie jeweils in die ausgewählten Abschnitte des context 'some description' {}
. Sie können beide Abhängigkeiten zwischen Ressourcen und zwischen Klassen überprüfen: Wenn beispielsweise angenommen wird, dass eine is_expected.to contain_class('parent_class_name')
enthält, können Sie die is_expected.to contain_class('parent_class_name')
hinzufügen. Müssen Sie das Verhalten in verschiedenen Betriebssystemen überprüfen? Es ist auch möglich: Wir geben einfach in einem separaten Kontext die notwendigen Fakten an:
context 'with Debian' do let(:facts) do { os: { architecture: 'amd64', distro: { codename: 'stretch', id: 'Debian', release: { full: '9.6', major: '9', minor: '6', }, }, family: 'Debian', name: 'Debian', release: { full: '9.6', major: '9', minor: '6', }, selinux: { enabled: false, }, }, osfamily: 'Debian', } end it { is_expected.to something } end
Soweit ich beim Schreiben von Tests festgestellt habe, können Sie mit dem Framework im Allgemeinen fast alles überprüfen, was möglicherweise benötigt wird. Das Vorhandensein von Tests hat mir einmal geholfen, als einige Parameter von den untergeordneten Klassen in die oberste Klasse des Moduls verschoben wurden: Sie zeigten, dass das Refactoring nichts kaputt machte und sich das Verhalten des gesamten Moduls nicht änderte.
Anstelle von Ausgabe
Wie bereits aus der allgemeinen Intonation des Artikels hervorgeht, bin ich sehr ermutigt darüber, wie sehr Puppet die Arbeit mit Modulen und Manifesten dank PDK erleichtert hat. Routinemaßnahmen werden automatisiert, Vorlagen werden nach Möglichkeit verwendet, Konfigurationen für gängige CI sind sofort verfügbar. Es mag wie eine Art Overhead erscheinen, und die Verwendung bringt möglicherweise nicht die erwarteten Früchte, aber es lohnt sich auf jeden Fall. Wenn Sie vergleichen, wie man Module ohne und mit PDK entwickelt, dann sieht es für mich so aus:
Entwicklung ohne Bärte PDK | PDK-Entwicklung |
---|
 |  |
Versuchen Sie, setzen Sie, machen Sie sich und Ihren Kollegen das Leben leichter. Gerne beantworte ich mögliche Fragen.
Möge die Atomatisierung bei uns sein!