Übergeben Sie Umgebungsvariablen an den Vagrant Shell Provisioner

76

Es sieht so aus, als würden beim Aufrufen Umgebungsvariablen übergeben vagrant upWenn Sie einen Ruby-Provisioner verwenden ist es einfach :

VAR=123 vagrant up

In der Vagrantdatei:

ENV['VAR']

Wie mache ich das mit dem :shellProvisioner? Einfach das zu tun scheint nicht zu funktionieren:

$VAR
Abdullah Jibaly
quelle

Antworten:

80

Seit Vagrant 1.8.0 können Sie die hässlichen Hacks aus den anderen Antworten hier vergessen. Verwenden Sie einfach die envOption für den Shell-Provisioner ( docs ).

Verwenden Sie es so in Ihrem Vagrantfile:

config.vm.provision "shell", path: "provisionscript.sh", env: {"MYVAR" => "value"}

Dadurch wird die Umgebung nur für das Bereitstellungsskript festgelegt. Wenn Sie eine persistente Umgebungsvariable benötigen, die für alle Prozesse in der VM festgelegt ist, ist dies für die Vagrant-Bereitstellung nicht möglich. Sehen Sie hier: Shell-Umgebungsvariablen in Vagrant-Dateien werden nur zuerst weitergegeben .

gertvdijk
quelle
In Vagrant 1.8.5 envscheint der Parameter nur zu funktionieren, wenn ein pathSkript verwendet wird, kein inlineSkript.
Spyle
1
@spyle Ich verwende Vagrant 1.8.5 (mit VirtualBox 5.1.2 unter Mac OS X 10.11.6) und envarbeite mit inline.
Jonatan
Hmm ... vermisse ich hier etwas? Das funktioniert bei mir nicht: config.vm.provision :shell, path: "bootstrap.sh", env: {"MYSQL_DB_USERNAME"=>"django", "MYSQL_DB_PASSWORD"=>"supersecretpasswordwasreplaced"} Auf der anderen Seite os.environ['MYSQL_DB_USERNAME'] gibt es einen Schlüsselfehler :(
Tadhg
1
@Tadhg Überprüfen Sie Ihre Vagrant-Version. Und vielleicht eine neue Frage stellen, wenn es nicht funktioniert? Möglicherweise handelt es sich um ein nicht verwandtes Problem (z. B. eine Vagrantfile-Version oder -Umgebung, die nicht in Ihrer Toolkette enthalten ist).
Gertvdijk
Version ist gut. Sie haben Recht
Tadhg
42

Es ist nicht ideal, aber ich habe das jetzt zum Laufen gebracht:

config.vm.provision "shell" do |s|
    s.inline = "VAR1 is $1 and VAR2 is $2"
    s.args   = "#{ENV['VAR1']} #{ENV['VAR2']}"
end
Abdullah Jibaly
quelle
3
Sie können auch ersetzen s.inlinedurch s.pathund das gleiche Skript verwenden Sie bestanden hätte :path => "". (Mein Provisioner besteht aus Hunderten von Zeilen und ist daher für Inlining
ungeeignet
3
Alternativ können Sie die Ruby-Methode mit einem :args => ""Parameter wie diesem verwenden .
Msanford
4
Solltest du wirklich ein Komma haben s.args?
Marius Gedminas
16

Ich kam mit dieser Lösung für die CentOS-basierte Bereitstellung: Platzieren Sie alle meine erforderlichen Umgebungsvariablen in /etc/profile.d/vagrant.sh Datei und dann in einem beliebigen Bereitstellungsskript darauf zu.

Zusamenfassend:

  $before_script = <<SCRIPT
  echo # vagrant profile script > /etc/profile.d/vagrant.sh
  echo export ENV_VAR1=foo.com/bar >> /etc/profile.d/vagrant.sh
  echo export ENV_VAR2=bar.com/foo >> /etc/profile.d/vagrant.sh
  chmod +x /etc/profile.d/vagrant.sh
SCRIPT

  $after_script = <<SCRIPT
    rm -rf /etc/profile.d/vagrant.sh
SCRIPT

  config.vm.provision "shell", inline: $before_script
  config.vm.provision "shell", path: "build.sh"
  config.vm.provision "shell", inline: $after_script

Vollständig Vagrantfilefinden Sie hier https://gist.github.com/bivas/6192d6e422f8ff87c29d

Bivas
quelle
Funktioniert für mich unter Linux (für eine Ubuntu-basierte VM). Genial!
Nikos Alexandris
1
Allerdings gibt es jetzt vagrantup.com/docs/provisioning/shell.html#env . Ich habe es gesehen, aber aufgrund des Mangels an Beispielen habe ich es übersprungen. Ein Kollege wies darauf hin, dass es funktioniert.
Nikos Alexandris
1
@ NikosAlexandris: Siehe meine Antwort :)
gertvdijk
16

Für die Nachwelt (auch bekannt als falls ich es noch einmal google) ... Es ist möglich, Schlüssel-Wert-Paare über env zu übergeben :

box.vm.provision :shell do |s|
  s.env = {AWS_ACCESS_KEY:ENV['AWS_ACCESS_KEY'], AWS_SECRET_KEY:ENV['AWS_SECRET_KEY']}
  s.path = 'scripts/bootstrap.sh'
end

Verweisen Sie dann in Ihrem Skript auf sie:

export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY}
export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_KEY}

Bonusfunktion:

Vagrant übernimmt das Zitieren von Umgebungsvariablenwerten, die Schlüssel bleiben jedoch unberührt

Al Belsky
quelle
Siehe auch Antwort von @gertvdijk (Ich hatte meine Seite beim Posten nicht aktualisiert)
Al Belsky
8

Sie können #{ENV['VAR']}in einem Inline-Skript Folgendes verwenden: z.

config.vm.provision "shell", inline: <<-END
  ...
  # Install my dotfiles are there.  If you're in a hurry you can do
  # SKIP_DOTFILES=1 vagrant up
  if ! [ -d /home/vagrant/dotfiles ] && [ -z '#{ENV['SKIP_DOTFILES']}']; then
    if ! [ -x /usr/bin/git ]; then
      DEBIAN_FRONTEND=noninteractive apt-get install -y git
    fi
    su - vagrant -c 'git clone https://github.com/mgedmin/dotfiles'
    su - vagrant -c 'dotfiles/install.sh'
  fi
  ...
  END

Beispiel aus einer funktionierenden Vagrant-Datei.

Dies hat einige Nachteile: Wenn $ VAR einfache Anführungszeichen enthält, werden die Dinge kaputt gehen.

Marius Gedminas
quelle
Natürlich stelle ich fest, dass @Bob im Wesentlichen die gleiche Antwort (im NEW WAY-Bit) lieferte, direkt nachdem ich meine gepostet habe . Augh!
Marius Gedminas
7

Wenn jemand nach dem Festlegen von Variablen in der Umgebung des Bereitstellungsskripts sucht, hat dies für mich funktioniert.

config.vm.provision :shell, :inline => <<-SH
  export GRAPHITE_HOST=192.168.33.10
  /vagrant/install_app_with_monitoring.sh
SH

Beachten Sie, dass dies voraussetzt, dass Sie Ihr Arbeitsverzeichnis wie /vagrantauf der VM freigeben, dies sollte jedoch die Standardeinstellung sein.

Mat Schaffer
quelle
aber warum nicht drinnen install_app_with_monitoring.sh?
Stephan Bijzitter
Hauptsächlich, um das Wissen am selben Ort zu halten. Ein Beispiel finden Sie hier github.com/forty9ten/monitoring-with-graphite/blob/master/… Wenn Sie die Variable in der Vagrant-Datei belassen, können Sie auf einfache Weise die Parität zwischen private_networkund sicherstellen GRAPHITE_HOST. Könnte sogar noch einen Schritt weiter gehen und export GRAPHITE_HOST=#{ip}eine einzelne gemeinsame Rubinvariante referenzieren.
Mat Schaffer
4

Die meisten dieser Antworten scheinen veraltet zu sein. Mit Vagrant 2.1.1 hat das bei mir funktioniert:

  VAGRANTFILE_API_VERSION = "2" //...

  machine.vm.provision "shell", 
    env: {
      "ELASTIC_XMS" => servers["elastic"]["memory_xms"], 
      "ELASTIC_XMX" => servers["elastic"]["memory_xmx"]
    }, 
    inline: "sed -i -e \"s/-Xms.*/$ELASTIC_XMS/g\" /etc/elasticsearch/jvm.options"
OZZIE
quelle
2

Das Vagrant-Env- Plugin macht genau das. Damit können Sie der .envDatei im lokalen Verzeichnis Umgebungsvariablen hinzufügen , die in die VagrantDatei geladen werden. Ich schlage vor, .envin Ihrem zu bleiben .gitignore, auf diese Weise haben Sie Ihre Privatsphäre garantiert.

Shairon Toledo
quelle
1
Plugin starb im Jahr 2015, dies ist nicht aktuell.
Ligemer
1

So funktioniert es.

Ich ging von der Verwendung des Vagabundpuppen-Provisioners zur Verwendung des Shell-Provisioners über. Ich tat dies hauptsächlich, weil ich Marionette wollte, um nicht als root zu laufen, Shell-Anbieter gibt Ihnen: privileged => false.

MEIN ALTER WEG:

config.vm.provision :puppet do |puppet|
  puppet.module_path = ENV.fetch('MODULES_PATH', 'modules')
  puppet.manifests_path = ENV.fetch('MANIFESTS_PATH', 'manifests')
  puppet.manifest_file  = ENV.fetch('MANIFEST_FILE', 'site.pp')
  puppet.options = "--debug"
end

MEIN NEUER WEG:

config.vm.provision :shell, :privileged => false do |shell|
  shell.inline = "puppet apply --debug --modulepath '/vagrant/#{ENV.fetch('MODULES_PATH', 'modules')}' --detailed-exitcodes '/vagrant/#{ENV.fetch('MANIFESTS_PATH', 'manifests')}/#{ENV.fetch('MANIFEST_FILE', 'site.pp')}'"
end
Kuberchaun
quelle
1

Sie können einfach angeben, shellob Sie inlinein Ihrer VagrantfileDatei Folgendes verwenden möchten:

config.vm.provision "shell", inline: %Q(/usr/bin/env FOO=1 BAR=1 bash /path/to/script.sh)

Oder laden Sie einige zusätzliche Variablen aus der YAML-Datei:

require 'yaml'
dir = File.dirname(File.expand_path(__FILE__))
vconfig = YAML::load_file("#{dir}/config.yml")
config.vm.provision "shell", inline: %Q(/usr/bin/env FOO=#{vconfig['foo']} bash /path/to/script.sh)

Alternativ können Sie einige optionale Argumente über die Befehlszeile implementieren, z.

# Parse optional arguments.
opts = GetoptLong.new(
  [ '--foo',  GetoptLong::OPTIONAL_ARGUMENT ], # With optional parameter.
  [ '--bar',  GetoptLong::OPTIONAL_ARGUMENT ], # With optional parameter.files.
)
opts.each do |opt, arg|
  case opt
    when '--foo'
      foo==arg
    when '--bar'
      bar=arg
  end
end

dann benutze: opt['--foo'].to_s .

Siehe auch: Wie übergebe ich Parameter an Vagrant und habe sie im Umfang des Kochbuchs?

Kenorb
quelle
-2

das hat bei mir funktioniert

VAGRANTFILE_API_VERSION = "2"

kettle_dir = ENV['KETTLE_DIR']
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
   config.vm.synced_folder kettle_dir, "/pentaho"
   config.vm.box = "ubuntu/trusty64"
end
itb
quelle
Können Sie etwas näher erläutern, warum dies die richtige Antwort ist?
rfornal
Dies verwendet eine Umgebungsvariable in der Vagrant-Datei, legt jedoch keine für den Provisioner fest, wie in der Frage gestellt.
Btubbs
-3

Auf einer Ubutnu-Box habe ich in meiner bootstrap.sh einfach Folgendes gemacht:

echo "DBHOST=localhost" >> /etc/environment
echo "DBNAME=foo" >> /etc/environment
echo "DBUSER=root" >> /etc/environment
echo "DBPASSWD=root" >> /etc/environment
yerachw
quelle