Exécuter le script sur la machine hôte pendant le vagabond

36

Je voudrais exécuter un script bash sur la machine hôte lorsque vagrant approvisionne le serveur.

Quelle serait la meilleure méthode pour y parvenir?

digital
la source

Réponses:

29

Au moins deux plugins qui devraient aider:

Si vous ne vous souciez pas que le script est exécuté sur (presque) tous vagrant Commandes, vous pouvez également simplement utiliser Shell (ou utiliser la magie ruby) dans Vagrantfile:

system('./myscript.sh')

Vagrant.configure('2') do |config|
  # ...
end
tmatilai
la source
1
Les déclencheurs vagabonds ressemblent exactement à ce dont j'ai besoin.
digital
Où avez-vous trouvé cette fonction system ()? Je ne trouve aucune documentation à ce sujet n'importe où ...
Cristiano Fontes
1
@CristianoFontes, c'est dans le Kernel module, documenté ici . le Kernel le module est inclus dans le Object classe, donc ses méthodes sont disponibles dans tous les domaines.
tmatilai
1
Stupide que je suis. Je cherchais dans la documentation vagabonde. Merci!
Cristiano Fontes
22

Solution simple (et complète)

(Je dis complète car la réponse acceptée ne vérifie pas si l'utilisateur utilise vagabond. Le script est donc exécuté sur chaque commande, ce qui n'est pas ce que souhaite le PO.)

Il existe cependant une solution simple à cela.

ARGV[0] est le premier argument de la commande entrée et peut être up, down, status, etc. Il suffit de vérifier la valeur de ARGV[0] dans votre Vagrantfile.


Quelque chose comme ça va faire:

system("
    if [ #{ARGV[0]} = 'up' ]; then
        echo 'You are doing vagrant up and can execute your script'
        ./myscript.sh
    fi
")

Vagrant.configure('2') do |config|
  # ...
end
Mick
la source
1
Salut, Mick ... Bonne réponse, merci. Mais je ne peux pas obtenir si [# {ARGV [0]} = 'up']; travailler sur des fenêtres. Il ne trouve jamais l'argument
Cristiano Fontes
1
Cela exécute votre script avant d’exécuter quoi que ce soit, quelle que soit sa position dans Vagrantfile. Cela pourrait suffire pour ce que vous faites, mais le plugin vagrant-triggers était ce dont j'avais besoin ...
Vigintas Labakojis
2
@CristianoFontes vous pouvez faire le test argv en ruby ​​en dehors de l'appel système et cela fonctionnera sous windows et * nix. J'utilise ceci pour définir une variable globale ruby ​​indiquant que le provisionnement est en cours en recherchant la commande up ou provision sur la ligne de commande: if ARGV [0] = ~ / ^ up | provision $ / i et non ARGV.include? (" --no-provision ") $ provisioning = true sinon $ provisioning = false fin
Rhubarb
Comme le recommande Vagrant, c’est en fait une mauvaise pratique. Vous devez écrire un plug-in pour vous connecter à la commande "up". Vous pouvez spécifier l’un des éléments suivants: avant, après et autour de l’exécution.
SilentICE
1
@Mick c'est juste des documents Vagrant ( docs.vagrantup.com/v2/plugins/commands.html ). Cela crée également un script fragile, car vous ne pouvez pas être certain que dans les cas d'appel, argv [0] est "en place" plutôt que de dire un drapeau. De plus, si vous passez au rubis brut, vous êtes en train d'expliquer l'encapsulation que le framework est censé fournir. Il y a des mécanismes exposés pour faire ceci correctement alors IMHO vous devriez les utiliser autant que possible
SilentICE
9

Placez ceci près du sommet de votre Vagrantfile:

module LocalCommand
    class Config < Vagrant.plugin("2", :config)
        attr_accessor :command
    end

    class Plugin < Vagrant.plugin("2")
        name "local_shell"

        config(:local_shell, :provisioner) do
            Config
        end

        provisioner(:local_shell) do
            Provisioner
        end
    end

    class Provisioner < Vagrant.plugin("2", :provisioner)
        def provision
            result = system "#{config.command}"
        end
    end
end

Ensuite, invoquez simplement dans votre Vagrantfile comme ceci:

config.vm.provision "list-files", type: "local_shell", command: "ls"

Et via la ligne de commande comme ceci:

vagrant provision --provision-with list-files

C’est un peu un bidouillage, ça ressemble à un plug-in, mais ce n’est vraiment pas le cas vagrant plugin list ). Je ne recommande pas de le faire de cette façon, sauf que cela présente l'avantage de ne pas avoir besoin d'installer un plugin. Votre Vagrantfile fonctionnera donc sur tout ordinateur prenant en charge la dernière version de la configuration (version 2 à la date d'écriture). Bien que cela semble prometteur, il y a aussi tout le problème multi-plateforme de la commande que vous émettez. Vous devrez prendre en considération si vous voulez que votre Vagrantfile soit portable, mais cela devrait vous aider à démarrer.

Joel B
la source
1
Bonne réponse, je vais l'utiliser pour configurer un transfert de port faible.
poindexter
4

En ligne avec ce que @tmatilai a dit à propos de l'utilisation

system('./myscript.sh')

Je l’ai trouvé très utile pour des commandes ponctuelles telles que l’installation de commandes vagrant ou un approvisionneur qui pourrait ne pas être installé sur le système. J'évite juste de le refaire chaque fois que j'invoque le vagrant commandes en ajoutant un sed pour commenter automatiquement la Vagrantfile.

Par exemple:

system('vagrant plugin install vagrant-fabric && (pip install fabric jinja2 || sudo pip install fabric jinja2) && sed -i -e "s/^system/#system/g" Vagrantfile')

Et j'en fais la première ligne de mon fichier Vagrant. De cette façon, il installera d’abord le plugin vagant-fabric, fabric et jinja (essaiera d’abord sans sudo pour virtualenvs et avec sudo si cela échoue) et alors la ligne se commente.

kenorb
la source
Il serait plus simple de simplement mettre la liste des plug-ins vagpents dans grep au lieu de supprimer le commentaire de Vagrantfile, ce qui pourrait poser problème à d’autres membres de votre équipe. if [[ $(vagrant plugin list | grep -c vagrant-host-shell) == "0" ]] then vagrant plugin install vagrant-host-shell fi
Jordan
Le problème, c’est qu’il sera déclenché par d’autres commandes, que se passe-t-il si vous exécutez vagrant status avant vagrant up...
Mick
1

Sur la base de la réponse de @ tmatilai mais mise à jour pour 2019, les déclencheurs de vagabonds ont été fusionnés dans Vagrant. Donc, vous pouvez maintenant faire quelque chose comme ceci:

node.trigger.before [:up, :provision] do |trigger|
  trigger.info = "Running ./myscript.sh locally..."
  trigger.run = {path: "./myscript.sh"}
end

Ce bloc va à l'intérieur de config.vm.define. Documentation complémentaire: https://www.vagrantup.com/docs/triggers/

Sean Hood
la source