├── lib ├── vagrant-host-shell │ ├── version.rb │ ├── errors.rb │ ├── plugin.rb │ ├── provisioner.rb │ └── config.rb └── vagrant-host-shell.rb ├── .gitignore ├── Gemfile ├── examples └── Vagrantfile ├── Rakefile ├── README.md ├── vagrant-host-shell.gemspec └── LICENSE.txt /lib/vagrant-host-shell/version.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins 2 | module HostShell 3 | VERSION = '0.0.4' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | .vagrant 19 | -------------------------------------------------------------------------------- /lib/vagrant-host-shell.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins 2 | module HostShell 3 | lib_path = Pathname.new(File.expand_path("../vagrant-host-shell", __FILE__)) 4 | autoload :Errors, lib_path.join("errors") 5 | end 6 | end 7 | 8 | require 'vagrant-host-shell/plugin' 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in vagrant-host-shell.gemspec 4 | gemspec 5 | 6 | # We depend on Vagrant for development, but we don't add it as a 7 | # gem dependency because we expect to be installed within the 8 | # Vagrant environment itself using `vagrant plugin`. 9 | gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git" 10 | -------------------------------------------------------------------------------- /examples/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 5 | require 'vagrant-host-shell' 6 | 7 | Vagrant.configure("2") do |config| 8 | config.vm.box = "precise64" 9 | 10 | config.vm.provision :host_shell do |host_shell| 11 | host_shell.inline = 'touch /tmp/hostshell-works && echo hello from the host && hostname 1>&2' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | 4 | # Immediately sync all stdout so that tools like buildbot can 5 | # immediately load in the output. 6 | $stdout.sync = true 7 | $stderr.sync = true 8 | 9 | # Change to the directory of this file. 10 | Dir.chdir(File.expand_path("../", __FILE__)) 11 | 12 | # This installs the tasks that help with gem creation and 13 | # publishing. 14 | Bundler::GemHelper.install_tasks 15 | 16 | -------------------------------------------------------------------------------- /lib/vagrant-host-shell/errors.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins::HostShell::Errors 2 | 3 | class VagrantHostShellError < Vagrant::Errors::VagrantError; end 4 | 5 | class NonZeroStatusError < VagrantHostShellError 6 | def initialize(command, exit_code) 7 | @command = command 8 | @exit_code = exit_code 9 | super nil 10 | end 11 | 12 | def error_message 13 | "Command [#{@command}] exited with non-zero status [#{@exit_code}]" 14 | end 15 | 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/vagrant-host-shell/plugin.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'vagrant' 3 | rescue LoadError 4 | raise 'The vagrant-host-shell plugin must be run within Vagrant.' 5 | end 6 | 7 | module VagrantPlugins::HostShell 8 | class Plugin < Vagrant.plugin('2') 9 | name 'vagrant-host-shell' 10 | description <<-DESC.gsub(/^ +/, '') 11 | A simple provisioner to run commands on the host at machine 12 | boot, instead of the guest. 13 | DESC 14 | 15 | config(:host_shell, :provisioner) do 16 | require_relative 'config' 17 | Config 18 | end 19 | 20 | provisioner(:host_shell) do 21 | require_relative 'provisioner' 22 | Provisioner 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/vagrant-host-shell/provisioner.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins::HostShell 2 | class Provisioner < Vagrant.plugin('2', :provisioner) 3 | def provision 4 | result = Vagrant::Util::Subprocess.execute( 5 | 'bash', 6 | '-c', 7 | config.inline, 8 | :notify => [:stdout, :stderr], 9 | :workdir => config.cwd, 10 | :env => {PATH: ENV["VAGRANT_OLD_ENV_PATH"]}, 11 | ) do |io_name, data| 12 | @machine.env.ui.info "[#{io_name}] #{data}" 13 | end 14 | 15 | if config.abort_on_nonzero && !result.exit_code.zero? 16 | raise VagrantPlugins::HostShell::Errors::NonZeroStatusError.new(config.inline, result.exit_code) 17 | end 18 | 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vagrant-host-shell plugin 2 | 3 | a vagrant provisioner to run commands on the host when a VM boots. 4 | 5 | simple example based on question asked [on vagrant mailing list](https://groups.google.com/forum/#!topic/vagrant-up/CsNx-FErplY) 6 | 7 | ## example usage 8 | 9 | Install as a plugin: 10 | 11 | ``` 12 | vagrant plugin install vagrant-host-shell 13 | ``` 14 | 15 | Add this to `Vagrantfile`: 16 | 17 | ```ruby 18 | config.vm.provision :host_shell do |host_shell| 19 | host_shell.inline = 'touch /tmp/hostshell-works && echo hello from the host && hostname 1>&2' 20 | end 21 | ``` 22 | 23 | Run `vagrant up` (or `vagrant provision` if machine is already running.) 24 | 25 | Observe that `/tmp/hostshell-works` is present on your host, and that the provisioner output: 26 | 27 | ``` 28 | [stdout] hello from the host 29 | [stderr] (your host's hostname) 30 | ``` 31 | -------------------------------------------------------------------------------- /vagrant-host-shell.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | 5 | require 'vagrant-host-shell/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = "vagrant-host-shell" 9 | spec.version = VagrantPlugins::HostShell::VERSION 10 | spec.authors = ["Paul Hinze", "Carlos Brito Lage"] 11 | spec.email = ["paul.t.hinze@gmail.com", "carlos@compstak.com"] 12 | spec.description = %q{a vagrant provisioner to run commands on the host} 13 | spec.summary = %q{a vagrant provisioner to run commands on the host} 14 | spec.homepage = "" 15 | spec.license = "MIT" 16 | 17 | spec.files = `git ls-files`.split($/) 18 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 19 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 20 | spec.require_paths = ["lib"] 21 | 22 | spec.add_development_dependency "bundler", "~> 1.3" 23 | spec.add_development_dependency "rake" 24 | end 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Paul Hinze 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /lib/vagrant-host-shell/config.rb: -------------------------------------------------------------------------------- 1 | module VagrantPlugins::HostShell 2 | class Config < Vagrant.plugin('2', :config) 3 | attr_accessor :inline 4 | attr_accessor :cwd 5 | attr_accessor :abort_on_nonzero 6 | 7 | def initialize 8 | @inline = UNSET_VALUE 9 | @cwd = UNSET_VALUE 10 | @abort_on_nonzero = UNSET_VALUE 11 | end 12 | 13 | def finalize! 14 | @inline = nil if @inline == UNSET_VALUE 15 | @cwd = nil if @cwd == UNSET_VALUE 16 | @abort_on_nonzero = false if @abort_on_nonzero == UNSET_VALUE 17 | end 18 | 19 | def validate(machine) 20 | errors = _detected_errors 21 | 22 | unless inline 23 | errors << ':host_shell provisioner requires inline to be set' 24 | end 25 | 26 | unless abort_on_nonzero.is_a?(TrueClass) || abort_on_nonzero.is_a?(FalseClass) 27 | errors << ':host_shell provisioner requires abort_on_nonzero to be a boolean' 28 | end 29 | 30 | unless cwd.is_a?(String) || cwd.nil? 31 | errors << ':host_shell provisioner requires cwd to be a string or nil' 32 | end 33 | 34 | { 'host shell provisioner' => errors } 35 | end 36 | end 37 | end 38 | --------------------------------------------------------------------------------