vagrant-shell 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ # OS-specific
2
+ .DS_Store
3
+
4
+ # Bundler/Rubygems
5
+ *.gem
6
+ .bundle
7
+ pkg/*
8
+ tags
9
+ Gemfile.lock
10
+
11
+ # Vagrant
12
+ .vagrant
13
+ Vagrantfile
14
+ !example_box/Vagrantfile
data/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # 0.2.2 (April 18, 2013)
2
+
3
+ * Fix crashing bug with incorrect provisioner arguments.
4
+
5
+ # 0.2.1 (April 16, 2013)
6
+
7
+ * Got rid of extranneous references to old SSH settings.
8
+
9
+ # 0.2.0 (April 16, 2013)
10
+
11
+ * Add support for `vagrant ssh -c` [GH-42]
12
+ * Ability to specify a timeout for waiting for instances to become ready. [GH-44]
13
+ * Better error message if instance didn't become ready in time.
14
+ * Connection can now be done using IAM profiles. [GH-41]
15
+
16
+ # 0.1.3 (April 9, 2013)
17
+
18
+ * The `AWS_ACCESS_KEY` and `AWS_SECRET_KEY` will be used if available
19
+ and no specific keys are set in the Vagrantfile. [GH-33]
20
+ * Fix issues with SSH on VPCs, the correct IP is used. [GH-30]
21
+ * Exclude the ".vagrant" directory from rsync.
22
+ * Implement `:disabled` flag support for shared folders. [GH-29]
23
+ * `aws.user_data` to specify user data on the instance. [GH-26]
24
+
25
+ # 0.1.2 (March 22, 2013)
26
+
27
+ * Choose the proper region when connecting to AWS. [GH-9]
28
+ * Configurable SSH port. [GH-13]
29
+ * Support other AWS-compatible API endpoints with `config.endpoint`
30
+ and `config.version`. [GH-6]
31
+ * Disable strict host key checking on rsync so known hosts aren't an issue. [GH-7]
32
+
33
+ # 0.1.1 (March 18, 2013)
34
+
35
+ * Up fog dependency for Vagrant 1.1.1
36
+
37
+ # 0.1.0 (March 14, 2013)
38
+
39
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2013 Mitchell Hashimoto
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # Vagrant Shell Provider
2
+
3
+ This is a [Vagrant](http://www.vagrantup.com) 1.2+ plugin that adds a
4
+ shell provider to Vagrant, allowing Vagrant to control and provision
5
+ machines using shell scripts. It's meant to be customized with scripts
6
+ for Xen, Docker, etc.
7
+
8
+ **NOTE:** This plugin requires Vagrant 1.2+,
9
+
10
+ ## Usage
11
+
12
+ TODO - this gem is a work in progress
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec/core/rake_task'
4
+
5
+ # Immediately sync all stdout so that tools like buildbot can
6
+ # immediately load in the output.
7
+ $stdout.sync = true
8
+ $stderr.sync = true
9
+
10
+ # Change to the directory of this file.
11
+ Dir.chdir(File.expand_path("../", __FILE__))
12
+
13
+ # This installs the tasks that help with gem creation and
14
+ # publishing.
15
+ Bundler::GemHelper.install_tasks
16
+
17
+ # Install the `spec` task so that we can run tests.
18
+ RSpec::Core::RakeTask.new
19
+
20
+ # Default task is to run the unit tests
21
+ task :default => "spec"
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module Shell
3
+ module Action
4
+ # This can be used with "Call" built-in to check if the machine
5
+ # is created and branch in the middleware.
6
+ class IsCreated
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:result] = env[:machine].state.id != :not_created
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module Shell
3
+ module Action
4
+ class MessageAlreadyCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_shell.already_created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module Shell
3
+ module Action
4
+ class MessageNotCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info(I18n.t("vagrant_shell.not_created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ module Action
6
+ # This action reads the SSH info for the machine and puts it into the
7
+ # `:machine_ssh_info` key in the environment.
8
+ class ReadSSHInfo
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new("vagrant_shell::action::read_ssh_info")
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_ssh_info] = read_ssh_info(env[:machine])
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def read_ssh_info(machine)
21
+ return nil if machine.id.nil?
22
+
23
+ # Read the DNS info
24
+ host,port = `#{machine.provider_config.script} ssh-info #{machine.id}`.split(/\s+/)[0,2]
25
+ return {
26
+ :host => host,
27
+ :port => port
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ module Action
6
+ # This action reads the state of the machine and puts it in the
7
+ # `:machine_state_id` key in the environment.
8
+ class ReadState
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new("vagrant_shell::action::read_state")
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_state_id] = read_state(env[:machine])
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def read_state(machine)
21
+ return :not_created if machine.id.nil?
22
+
23
+ # Return the state
24
+ `#{machine.provider_config.script} read-state #{machine.id}`
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,109 @@
1
+ require "log4r"
2
+ require "pp"
3
+
4
+ require 'vagrant/util/retryable'
5
+
6
+ require 'vagrant-shell/util/timer'
7
+
8
+ module VagrantPlugins
9
+ module Shell
10
+ module Action
11
+ # This runs the configured instance.
12
+ class RunInstance
13
+ include Vagrant::Util::Retryable
14
+
15
+ def initialize(app, env)
16
+ @app = app
17
+ @logger = Log4r::Logger.new("vagrant_shell::action::run_instance")
18
+ end
19
+
20
+ def call(env)
21
+ # Initialize metrics if they haven't been
22
+ env[:metrics] ||= {}
23
+
24
+ # Get the configs
25
+ provider_config = env[:machine].provider_config
26
+ ami = provider_config.ami
27
+ user_data = provider_config.user_data
28
+
29
+ # Launch!
30
+ env[:ui].info(I18n.t("vagrant_shell.launching_instance"))
31
+ env[:ui].info(" -- AMI: #{ami}")
32
+
33
+ begin
34
+ # Immediately save the ID since it is created at this point.
35
+ env[:machine].id = `#{env[:machine].provider_config.script} run-instance #{ami}`.split(/\s+/)[0]
36
+ rescue Errors::ComputeError => e
37
+ raise Errors::ShellError, :message => e.message
38
+ end
39
+
40
+
41
+ # Wait for the instance to be ready first
42
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
43
+ tries = provider_config.instance_ready_timeout / 2
44
+
45
+ env[:ui].info(I18n.t("vagrant_shell.waiting_for_ready"))
46
+ begin
47
+ retryable(:on => Shell::Errors::TimeoutError, :tries => tries) do
48
+ # If we're interrupted don't worry about waiting
49
+ next if env[:interrupted]
50
+
51
+ # Wait for the server to be ready
52
+ true
53
+ end
54
+ rescue Shell::Errors::TimeoutError
55
+ # Delete the instance
56
+ terminate(env)
57
+
58
+ # Notify the user
59
+ raise Errors::InstanceReadyTimeout,
60
+ timeout: provider_config.instance_ready_timeout
61
+ end
62
+ end
63
+
64
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
65
+
66
+ if !env[:interrupted]
67
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
68
+ # Wait for SSH to be ready.
69
+ env[:ui].info(I18n.t("vagrant_shell.waiting_for_ssh"))
70
+ while true
71
+ # If we're interrupted then just back out
72
+ break if env[:interrupted]
73
+ break if env[:machine].communicate.ready?
74
+ sleep 2
75
+ end
76
+ end
77
+
78
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
79
+
80
+ # Ready and booted!
81
+ env[:ui].info(I18n.t("vagrant_shell.ready"))
82
+ end
83
+
84
+ # Terminate the instance if we were interrupted
85
+ terminate(env) if env[:interrupted]
86
+
87
+ @app.call(env)
88
+ end
89
+
90
+ def recover(env)
91
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
92
+
93
+ if env[:machine].provider.state.id != :not_created
94
+ # Undo the import
95
+ terminate(env)
96
+ end
97
+ end
98
+
99
+ def terminate(env)
100
+ destroy_env = env.dup
101
+ destroy_env.delete(:interrupted)
102
+ destroy_env[:config_validate] = false
103
+ destroy_env[:force_confirm_destroy] = true
104
+ env[:action_runner].run(Action.action_destroy, destroy_env)
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,67 @@
1
+ require "log4r"
2
+
3
+ require "vagrant/util/subprocess"
4
+
5
+ require "vagrant/util/scoped_hash_override"
6
+
7
+ module VagrantPlugins
8
+ module Shell
9
+ module Action
10
+ # This middleware uses `rsync` to sync the folders over to the
11
+ # Shell instance.
12
+ class SyncFolders
13
+ include Vagrant::Util::ScopedHashOverride
14
+
15
+ def initialize(app, env)
16
+ @app = app
17
+ @logger = Log4r::Logger.new("vagrant_shell::action::sync_folders")
18
+ end
19
+
20
+ def call(env)
21
+ @app.call(env)
22
+
23
+ ssh_info = env[:machine].ssh_info
24
+
25
+ env[:machine].config.vm.synced_folders.each do |id, data|
26
+ data = scoped_hash_override(data, :shell)
27
+
28
+ # Ignore disabled shared folders
29
+ next if data[:disabled]
30
+
31
+ hostpath = File.expand_path(data[:hostpath], env[:root_path])
32
+ guestpath = data[:guestpath]
33
+
34
+ # Make sure there is a trailing slash on the host path to
35
+ # avoid creating an additional directory with rsync
36
+ hostpath = "#{hostpath}/" if hostpath !~ /\/$/
37
+
38
+ env[:ui].info(I18n.t("vagrant_shell.rsync_folder",
39
+ :hostpath => hostpath,
40
+ :guestpath => guestpath))
41
+
42
+ # Create the guest path
43
+ env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
44
+ env[:machine].communicate.sudo(
45
+ "chown #{ssh_info[:username]} '#{guestpath}'")
46
+
47
+ # Rsync over to the guest path using the SSH info
48
+ command = [
49
+ "rsync", "--verbose", "--archive", "-z",
50
+ "--exclude", ".vagrant/",
51
+ "-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no -i '#{ssh_info[:private_key_path]}'",
52
+ hostpath,
53
+ "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
54
+
55
+ r = Vagrant::Util::Subprocess.execute(*command)
56
+ if r.exit_code != 0
57
+ raise Errors::RsyncError,
58
+ :guestpath => guestpath,
59
+ :hostpath => hostpath,
60
+ :stderr => r.stderr
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,24 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ module Action
6
+ # This terminates the running instance.
7
+ class TerminateInstance
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new("vagrant_shell::action::terminate_instance")
11
+ end
12
+
13
+ def call(env)
14
+ # Destroy the server and remove the tracking ID
15
+ env[:ui].info(I18n.t("vagrant_shell.terminating"))
16
+ `#{env[:machine].provider_config.script} terminate-instance #{env[:machine].id}`
17
+ env[:machine].id = nil
18
+
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ require "vagrant-shell/util/timer"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ module Action
6
+ # This is the same as the builtin provision except it times the
7
+ # provisioner runs.
8
+ class TimedProvision < Vagrant::Action::Builtin::Provision
9
+ def run_provisioner(env, name, p)
10
+ timer = Util::Timer.time do
11
+ super
12
+ end
13
+
14
+ env[:metrics] ||= {}
15
+ env[:metrics]["provisioner_times"] ||= []
16
+ env[:metrics]["provisioner_times"] << [name, timer]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module Shell
3
+ module Action
4
+ class WarnNetworks
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env[:machine].config.vm.networks.length > 0
11
+ env[:ui].warn(I18n.t("vagrant_shell.warn_networks"))
12
+ end
13
+
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,116 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module Shell
7
+ module Action
8
+ # Include the built-in modules so we can use them as top-level things.
9
+ include Vagrant::Action::Builtin
10
+
11
+ # This action is called to terminate the remote machine.
12
+ def self.action_destroy
13
+ Vagrant::Action::Builder.new.tap do |b|
14
+ b.use ConfigValidate
15
+ b.use TerminateInstance
16
+ end
17
+ end
18
+
19
+ # This action is called when `vagrant provision` is called.
20
+ def self.action_provision
21
+ Vagrant::Action::Builder.new.tap do |b|
22
+ b.use ConfigValidate
23
+ b.use Call, IsCreated do |env, b2|
24
+ if !env[:result]
25
+ b2.use MessageNotCreated
26
+ next
27
+ end
28
+
29
+ b2.use Provision
30
+ b2.use SyncFolders
31
+ end
32
+ end
33
+ end
34
+
35
+ # This action is called to read the SSH info of the machine. The
36
+ # resulting state is expected to be put into the `:machine_ssh_info`
37
+ # key.
38
+ def self.action_read_ssh_info
39
+ Vagrant::Action::Builder.new.tap do |b|
40
+ b.use ConfigValidate
41
+ b.use ReadSSHInfo
42
+ end
43
+ end
44
+
45
+ # This action is called to read the state of the machine. The
46
+ # resulting state is expected to be put into the `:machine_state_id`
47
+ # key.
48
+ def self.action_read_state
49
+ Vagrant::Action::Builder.new.tap do |b|
50
+ b.use ConfigValidate
51
+ b.use ReadState
52
+ end
53
+ end
54
+
55
+ # This action is called to SSH into the machine.
56
+ def self.action_ssh
57
+ Vagrant::Action::Builder.new.tap do |b|
58
+ b.use ConfigValidate
59
+ b.use Call, IsCreated do |env, b2|
60
+ if !env[:result]
61
+ b2.use MessageNotCreated
62
+ next
63
+ end
64
+
65
+ b2.use SSHExec
66
+ end
67
+ end
68
+ end
69
+
70
+ def self.action_ssh_run
71
+ Vagrant::Action::Builder.new.tap do |b|
72
+ b.use ConfigValidate
73
+ b.use Call, IsCreated do |env, b2|
74
+ if !env[:result]
75
+ b2.use MessageNotCreated
76
+ next
77
+ end
78
+
79
+ b2.use SSHRun
80
+ end
81
+ end
82
+ end
83
+
84
+ # This action is called to bring the box up from nothing.
85
+ def self.action_up
86
+ Vagrant::Action::Builder.new.tap do |b|
87
+ b.use ConfigValidate
88
+ b.use Call, IsCreated do |env, b2|
89
+ if env[:result]
90
+ b2.use MessageAlreadyCreated
91
+ next
92
+ end
93
+
94
+ b2.use TimedProvision
95
+ b2.use SyncFolders
96
+ b2.use WarnNetworks
97
+ b2.use RunInstance
98
+ end
99
+ end
100
+ end
101
+
102
+ # The autoload farm
103
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
104
+ autoload :IsCreated, action_root.join("is_created")
105
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
106
+ autoload :MessageNotCreated, action_root.join("message_not_created")
107
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
108
+ autoload :ReadState, action_root.join("read_state")
109
+ autoload :RunInstance, action_root.join("run_instance")
110
+ autoload :SyncFolders, action_root.join("sync_folders")
111
+ autoload :TimedProvision, action_root.join("timed_provision")
112
+ autoload :WarnNetworks, action_root.join("warn_networks")
113
+ autoload :TerminateInstance, action_root.join("terminate_instance")
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,68 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The ID of the AMI to use.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :ami
10
+
11
+ # The timeout to wait for an instance to become ready.
12
+ #
13
+ # @return [Fixnum]
14
+ attr_accessor :instance_ready_timeout
15
+
16
+ # The user data string
17
+ #
18
+ # @return [String]
19
+ attr_accessor :user_data
20
+
21
+ # The shell script implementing some tech
22
+ #
23
+ # @return [String]
24
+ attr_accessor :script
25
+
26
+ def initialize
27
+ @ami = UNSET_VALUE
28
+ @instance_ready_timeout = UNSET_VALUE
29
+ @user_data = UNSET_VALUE
30
+ @script = UNSET_VALUE
31
+
32
+ # Internal state (prefix with __ so they aren't automatically
33
+ # merged)
34
+ @__finalized = false
35
+ end
36
+
37
+ #-------------------------------------------------------------------
38
+ # Internal methods.
39
+ #-------------------------------------------------------------------
40
+
41
+ def merge(other)
42
+ super.tap do |result|
43
+ end
44
+ end
45
+
46
+ def finalize!
47
+ # AMI must be nil, since we can't default that
48
+ @ami = nil if @ami == UNSET_VALUE
49
+
50
+ # Set the default timeout for waiting for an instance to be ready
51
+ @instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
52
+
53
+ # User Data is nil by default
54
+ @user_data = nil if @user_data == UNSET_VALUE
55
+
56
+ # No default shell script
57
+ @script = nil if @script == UNSET_VALUE
58
+
59
+ # Mark that we finalized
60
+ @__finalized = true
61
+ end
62
+
63
+ def validate(machine)
64
+ { "Shell Provider" => [ ] }
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,31 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ module Errors
6
+ class VagrantShellError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_shell.errors")
8
+ end
9
+
10
+ class ShellError < VagrantShellError
11
+ error_key(:shell_error)
12
+ end
13
+
14
+ class TimeoutError < VagrantShellError
15
+ error_key(:instance_ready_timeout)
16
+ end
17
+
18
+ class ComputeError < VagrantShellError
19
+ error_key(:instance_ready_timeout)
20
+ end
21
+
22
+ class InstanceReadyTimeout < VagrantShellError
23
+ error_key(:instance_ready_timeout)
24
+ end
25
+
26
+ class RsyncError < VagrantShellError
27
+ error_key(:rsync_error)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant Shell plugin must be run within Vagrant."
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < "1.2.0"
10
+ raise "The Vagrant Shell plugin is only compatible with Vagrant 1.2+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module Shell
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "Shell"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ machines with shell scripts.
20
+ DESC
21
+
22
+ config(:shell, :provider) do
23
+ require_relative "config"
24
+ Config
25
+ end
26
+
27
+ provider(:shell) do
28
+ # Setup logging and i18n
29
+ setup_logging
30
+ setup_i18n
31
+
32
+ # Return the provider
33
+ require_relative "provider"
34
+ Provider
35
+ end
36
+
37
+ # This initializes the internationalization strings.
38
+ def self.setup_i18n
39
+ I18n.load_path << File.expand_path("locales/en.yml", Shell.source_root)
40
+ I18n.reload!
41
+ end
42
+
43
+ # This sets up our log level to be whatever VAGRANT_LOG is.
44
+ def self.setup_logging
45
+ require "log4r"
46
+
47
+ level = nil
48
+ begin
49
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
50
+ rescue NameError
51
+ # This means that the logging constant wasn't found,
52
+ # which is fine. We just keep `level` as `nil`. But
53
+ # we tell the user.
54
+ level = nil
55
+ end
56
+
57
+ # Some constants, such as "true" resolve to booleans, so the
58
+ # above error checking doesn't catch it. This will check to make
59
+ # sure that the log level is an integer, as Log4r requires.
60
+ level = nil if !level.is_a?(Integer)
61
+
62
+ # Set the logging level on all "vagrant" namespaced
63
+ # logs as long as we have a valid level.
64
+ if level
65
+ logger = Log4r::Logger.new("vagrant_shell")
66
+ logger.outputters = Log4r::Outputter.stderr
67
+ logger.level = level
68
+ logger = nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,50 @@
1
+ require "log4r"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module Shell
6
+ class Provider < Vagrant.plugin("2", :provider)
7
+ def initialize(machine)
8
+ @machine = machine
9
+ end
10
+
11
+ def action(name)
12
+ # Attempt to get the action method from the Action class if it
13
+ # exists, otherwise return nil to show that we don't support the
14
+ # given action.
15
+ action_method = "action_#{name}"
16
+ return Action.send(action_method) if Action.respond_to?(action_method)
17
+ nil
18
+ end
19
+
20
+ def ssh_info
21
+ # Run a custom action called "read_ssh_info" which does what it
22
+ # says and puts the resulting SSH info into the `:machine_ssh_info`
23
+ # key in the environment.
24
+ env = @machine.action("read_ssh_info")
25
+ env[:machine_ssh_info]
26
+ end
27
+
28
+ def state
29
+ # Run a custom action we define called "read_state" which does
30
+ # what it says. It puts the state in the `:machine_state_id`
31
+ # key in the environment.
32
+ env = @machine.action("read_state")
33
+
34
+ state_id = env[:machine_state_id]
35
+
36
+ # Get the short and long description
37
+ short = I18n.t("vagrant_shell.states.short_#{state_id}")
38
+ long = I18n.t("vagrant_shell.states.long_#{state_id}")
39
+
40
+ # Return the MachineState object
41
+ Vagrant::MachineState.new(state_id, short, long)
42
+ end
43
+
44
+ def to_s
45
+ id = @machine.id.nil? ? "new" : @machine.id
46
+ "Shell (#{id})"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module Shell
3
+ module Util
4
+ class Timer
5
+ # A basic utility method that times the execution of the given
6
+ # block and returns it.
7
+ def self.time
8
+ start_time = Time.now.to_f
9
+ yield
10
+ end_time = Time.now.to_f
11
+
12
+ end_time - start_time
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Shell
3
+ VERSION = "0.2.3"
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ require "pathname"
2
+
3
+ require "vagrant-shell/plugin"
4
+
5
+ module VagrantPlugins
6
+ module Shell
7
+ lib_path = Pathname.new(File.expand_path("../vagrant-shell", __FILE__))
8
+ autoload :Action, lib_path.join("action")
9
+ autoload :Errors, lib_path.join("errors")
10
+
11
+ # This returns the path to the source of this plugin.
12
+ #
13
+ # @return [Pathname]
14
+ def self.source_root
15
+ @source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
16
+ end
17
+ end
18
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,59 @@
1
+ en:
2
+ vagrant_shell:
3
+ already_created: |-
4
+ The machine is already created.
5
+ launching_instance: |-
6
+ Launching an instance with the following settings...
7
+ not_created: |-
8
+ Instance is not created. Please run `vagrant up` first.
9
+ ready: |-
10
+ Machine is booted and ready for use!
11
+ rsync_folder: |-
12
+ Rsyncing folder: %{hostpath} => %{guestpath}
13
+ terminating: |-
14
+ Terminating the instance...
15
+ waiting_for_ready: |-
16
+ Waiting for instance to become "ready"...
17
+ waiting_for_ssh: |-
18
+ Waiting for SSH to become available...
19
+ warn_networks: |-
20
+ Warning! The Shell provider doesn't support any of the Vagrant
21
+ high-level network configurations (`config.vm.network`). They
22
+ will be silently ignored.
23
+
24
+ config:
25
+ ami_required: |-
26
+ An AMI must be configured via "ami"
27
+ private_key_missing: |-
28
+ The specified private key for Shell could not be found
29
+
30
+ errors:
31
+ shell_error: |-
32
+ There was an error talking to Shell. The error message is shown
33
+ below:
34
+
35
+ %{message}
36
+ instance_ready_timeout: |-
37
+ The instance never became "ready" in Shell. The timeout currently
38
+ set waiting for the instance to become ready is %{timeout} seconds.
39
+ Please verify that the machine properly boots. If you need more time
40
+ set the `instance_ready_timeout` configuration on the Shell provider.
41
+ rsync_error: |-
42
+ There was an error when attemping to rsync a share folder.
43
+ Please inspect the error message below for more info.
44
+
45
+ Host path: %{hostpath}
46
+ Guest path: %{guestpath}
47
+ Error: %{stderr}
48
+
49
+ states:
50
+ short_not_created: |-
51
+ not created
52
+ long_not_created: |-
53
+ The Shell instance is not created. Run `vagrant up` to create it.
54
+
55
+ short_running: |-
56
+ running
57
+ long_running: |-
58
+ The Shell instance is running. To stop this machine, you can run
59
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
@@ -0,0 +1,51 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+ require "vagrant-shell/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "vagrant-shell"
6
+ s.version = VagrantPlugins::Shell::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = [ "Tom Bombadil", "Mitchell Hashimoto" ]
9
+ s.email = [ "amanibhavam@destructuring.org", "mitchell@hashicorp.com" ]
10
+ s.homepage = "http://destructuring.org/vagrant-shell"
11
+ s.summary = "Enables Vagrant to manage machines using shell scripts"
12
+ s.description = "Enables Vagrant to manage machines using shell scripts"
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "vagrant-shell"
16
+
17
+ # The following block of code determines the files that should be included
18
+ # in the gem. It does this by reading all the files in the directory where
19
+ # this gemspec is, and parsing out the ignored files from the gitignore.
20
+ # Note that the entire gitignore(5) syntax is not supported, specifically
21
+ # the "!" syntax, but it should mostly work correctly.
22
+ root_path = File.dirname(__FILE__)
23
+ all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
24
+ all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
25
+ gitignore_path = File.join(root_path, ".gitignore")
26
+ gitignore = File.readlines(gitignore_path)
27
+ gitignore.map! { |line| line.chomp.strip }
28
+ gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
29
+
30
+ unignored_files = all_files.reject do |file|
31
+ # Ignore any directories, the gemspec only cares about files
32
+ next true if File.directory?(file)
33
+
34
+ # Ignore any paths that match anything in the gitignore. We do
35
+ # two tests here:
36
+ #
37
+ # - First, test to see if the entire path matches the gitignore.
38
+ # - Second, match if the basename does, this makes it so that things
39
+ # like '.DS_Store' will match sub-directories too (same behavior
40
+ # as git).
41
+ #
42
+ gitignore.any? do |ignore|
43
+ File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
44
+ File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
45
+ end
46
+ end
47
+
48
+ s.files = unignored_files
49
+ s.executables = unignored_files.map { |f| f[/^bin\/(.*)/, 1] }.compact
50
+ s.require_path = 'lib'
51
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-shell
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tom Bombadil
9
+ - Mitchell Hashimoto
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-05-01 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Enables Vagrant to manage machines using shell scripts
16
+ email:
17
+ - amanibhavam@destructuring.org
18
+ - mitchell@hashicorp.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - CHANGELOG.md
24
+ - Gemfile
25
+ - lib/vagrant-shell/action/is_created.rb
26
+ - lib/vagrant-shell/action/message_already_created.rb
27
+ - lib/vagrant-shell/action/message_not_created.rb
28
+ - lib/vagrant-shell/action/read_ssh_info.rb
29
+ - lib/vagrant-shell/action/read_state.rb
30
+ - lib/vagrant-shell/action/run_instance.rb
31
+ - lib/vagrant-shell/action/sync_folders.rb
32
+ - lib/vagrant-shell/action/terminate_instance.rb
33
+ - lib/vagrant-shell/action/timed_provision.rb
34
+ - lib/vagrant-shell/action/warn_networks.rb
35
+ - lib/vagrant-shell/action.rb
36
+ - lib/vagrant-shell/config.rb
37
+ - lib/vagrant-shell/errors.rb
38
+ - lib/vagrant-shell/plugin.rb
39
+ - lib/vagrant-shell/provider.rb
40
+ - lib/vagrant-shell/util/timer.rb
41
+ - lib/vagrant-shell/version.rb
42
+ - lib/vagrant-shell.rb
43
+ - LICENSE
44
+ - locales/en.yml
45
+ - Rakefile
46
+ - README.md
47
+ - vagrant-shell.gemspec
48
+ - .gitignore
49
+ homepage: http://destructuring.org/vagrant-shell
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: 1.3.6
67
+ requirements: []
68
+ rubyforge_project: vagrant-shell
69
+ rubygems_version: 1.8.25
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Enables Vagrant to manage machines using shell scripts
73
+ test_files: []