2013-01-10 3 views
16

Ich versuche, einen Shell-Provisioner zu erhalten, um die erneute Bereitstellung einer VM-Instanz zu verhindern, wenn dies bereits zuvor erfolgt ist.Vermeiden Sie die erneute Bereitstellung einer Vagrant-VM, wenn diese bereits bereitgestellt wurde.

Betrachten Sie das folgende Vagrantfile:

Vagrant::Config.run do |config| 
    config.vm.define :minimal do |config| 
    # Base image 
    config.vm.box = "lucid32" 
    config.vm.box_url = "http://files.vagrantup.com/lucid32.box" 

    config.vm.provision :shell, :inline => "mkdir /tmp/foobar" 
    end 
end 

Wenn Sie vagrant up minimal ausführen, wird es die Box und die Bereitstellung es zunächst erstellen. Wenn Sie dann vagrant provision minimal ausführen, versucht es die Box erneut zu erstellen, schlägt jedoch fehl (da das Verzeichnis/tmp/foobar bereits existiert).

Gibt es eine Möglichkeit, Vagrant daran zu erinnern, ob es in der Vergangenheit eine Maschine bereitgestellt hat und um eine spätere erneute Bereitstellung zu vermeiden?

Weiterer Kontext: Wenn ich vagrant up minimal laufen, meinen Host-Computer neu zu starten, und dann vagrant up minimal erneut ausführen, wird es versuchen, die Box zu reprovision und scheitert. Dies passiert ziemlich oft, da VirtualBox häufig Kernel Panics auf meinem Host-Computer verursacht.

Antwort

10

Dies ist möglicherweise nicht die Antwort, die Sie wollen, aber wenn Sie, dass mkdir auf ein mkdir -p ändern, wird es funktionieren;)

In allen Ernstes, aber ich glaube, Vagrant Versorger (das zu idempotent erwartet ist , wenn es das zweite Mal ausgeführt wird, wird es keine Aktion ausführen).

Es kann schwierig sein, echte Idempotenz zu erreichen, je nachdem, was Sie in Ihrem Bereitstellungsskript tun, aber mkdir -p ist ein guter Anfang. Sie könnten auch eine Flag-Datei auf dem System erstellen und zuerst das Vorhandensein dieser Flag-Datei prüfen; Wenn es existiert, nur exit 0.

+0

Making the provisioner Idempotent vernünftig zu sein scheint. Obwohl nicht unbedingt einfach. –

+1

Ich zerlege mein Bereitstellungsskript in Abschnitte, die von if-Anweisungen umgeben sind. Ich berühre eine Datei am Ende jedes Abschnitts und die if-Anweisung überprüft, ob diese Datei existiert. Daher wird jeder Codeabschnitt nur einmal ausgeführt. Dies fügt sehr wenig Komplexität hinzu und ich habe Funktionen zum Prüfen und Schreiben der Datei, um Unordnung zu vermeiden. Bis jetzt funktioniert das ziemlich gut. Ich würde auch vorschlagen, dass "test -d/pfad/zu/dir || mkdir/pfad/zu/dir" ein besserer Weg sein könnte, dieses spezielle Problem zu lösen. Es gibt auch -f für Dateien und -L für Symlinks. "man bash" hat mehr. – bogeymin

+5

Die einfache und dumme Möglichkeit, Idempotenz zu erstellen, besteht darin, am Ende der Bereitstellung (sofern alles erfolgreich war) "touch ~/.VM_PROVISIONED" zu markieren und am Anfang über '[-e ~ .VM_PROVISIONED]' zu prüfen. –

5

Haben Sie sich das angesehen?

vagrant up --no-provision

$ vagrant up --help 
Usage: vagrant up [vm-name] [options] [-h] 

    --[no-]provision    Enable or disable provisioning 
    --provision-with x,y,z  Enable only certain provisioners, by type. 
    --[no-]parallel    Enable or disable parallelism if provider supports it. 
    --provider provider   Back the machine with a specific provider. 
-h, --help      Print this help 
+0

Die Verwendung von --no-provision scheint die Bereitstellung unbedingt zu vermeiden. Wenn Sie die Option unter Verwendung eines Skripts bedingt verwenden, ist das zwar möglich, aber nicht ideal. –

4

Vagrant läuft normalerweise den Bereitstellungscode nur auf die erstenvagrant upund, wenn Sie es ausdrücklich so tun sagen zu, wie mit vagrant provision oder vagrant reload --provision. Es ist wirklich nicht nötig, alles zu tun, um die Provisioning-Skripts nicht erneut ausführen zu müssen. (Diese may not have been the case when you posted the question, however.)

Wenn Sie Chef oder Puppet für die Bereitstellung verwenden, sind sie bereits entworfen, um alles idempotent, und ich würde davon ausgehen, das gleiche gilt für Salt and Ansible.

Wenn Sie mit Shell-Skripten und Sie wollen, dass sie idempotent machen, können Sie für einige Zustand überprüfen (wie das Vorhandensein einer Datei) in einer if Aussage:

if [[! -f "$HOME/bin/something.sh" ]]; then 
    # install something.sh into ~/bin 
fi 

Ich habe eine bestimmte sehr allgemeine Antwort, da ich annehme, dass mkdir /tmp/foobar ist nicht wirklich was Sie versuchen zu erreichen, aber wenn es dann ja ist, fügen Sie -p hinzu.

+0

Vielen Dank für die Erwähnung, dass nur das Ausführen des Provisioners beim ersten Start eine relativ neue Änderung ist (vor 7 Monaten). –

-1

Ich bin nicht in der Lage, den Fehler zu wiederholen. Sobald eine Box fertig ist, sollte sie nicht bereitgestellt werden, es sei denn, Sie verwenden Einrichtungen, um dies explizit zu ermöglichen.

Noch wichtiger ist, sollte Provisioning immer idempotent sein, wie von vielen anderen bemerkt.

Idempotenz Ein Rezept kann mehrmals auf demselben System laufen und die Ergebnisse werden immer identisch sein. Eine Ressource wird in einem Rezept definiert, das dann die auf dem System auszuführenden Aktionen definiert. Der Chef-Client stellt sicher, dass keine Aktionen ausgeführt werden, wenn sich die Ressourcen nicht geändert haben und jede durchgeführte Aktion jedes Mal auf die gleiche Weise ausgeführt wird. Wenn ein Rezept erneut ausgeführt wird und nichts geändert hat, wird der Chef-Client nichts tun.

ref: https://docs.getchef.com/chef_why.html#idempotence

+0

Dies scheint zu passieren, wenn Sie zum ersten Mal 'vagrant up --some-option' aufrufen, diese Option zu erinnern. Wenn Sie also das nächste Mal 'vagrant up' ausführen, wird" --some-option "noch übergeben. Ich, ich, gerade getroffen, weil jemand dokumentiert zu verwenden "vagrant up --provision" ... und nach dem Neustart meiner Maschine habe ich ein 'vagrant up', und alles wurde ausgelöscht. – Danosaure

6

Wenn Sie ein Bash-Provisioning-Skript verwenden, stehen die Chancen wird es nicht idempotent werden.

Hier ist eine niedrige Stirn Beispiel dafür, wie zweimal zu vermeiden Provisioning:

PROVISIONED="/some-app-dir/PROVISIONED"; 

if [[ -f $PROVISIONED ]]; then 
    echo "Skipping provisioning"; 
    exit; 
else 
    echo "Provisioning"; 
fi 

#...do provisioning things 

touch $PROVISIONED; 
Verwandte Themen