vagrant-shell 0.2.11 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.11
1
+ 0.2.12
@@ -0,0 +1,111 @@
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
+ end
31
+ end
32
+ end
33
+
34
+ # This action is called to read the SSH info of the machine. The
35
+ # resulting state is expected to be put into the `:machine_ssh_info`
36
+ # key.
37
+ def self.action_read_ssh_info
38
+ Vagrant::Action::Builder.new.tap do |b|
39
+ b.use ConfigValidate
40
+ b.use ReadSSHInfo
41
+ end
42
+ end
43
+
44
+ # This action is called to read the state of the machine. The
45
+ # resulting state is expected to be put into the `:machine_state_id`
46
+ # key.
47
+ def self.action_read_state
48
+ Vagrant::Action::Builder.new.tap do |b|
49
+ b.use ConfigValidate
50
+ b.use ReadState
51
+ end
52
+ end
53
+
54
+ # This action is called to SSH into the machine.
55
+ def self.action_ssh
56
+ Vagrant::Action::Builder.new.tap do |b|
57
+ b.use ConfigValidate
58
+ b.use Call, IsCreated do |env, b2|
59
+ if !env[:result]
60
+ b2.use MessageNotCreated
61
+ next
62
+ end
63
+
64
+ b2.use SSHExec
65
+ end
66
+ end
67
+ end
68
+
69
+ def self.action_ssh_run
70
+ Vagrant::Action::Builder.new.tap do |b|
71
+ b.use ConfigValidate
72
+ b.use Call, IsCreated do |env, b2|
73
+ if !env[:result]
74
+ b2.use MessageNotCreated
75
+ next
76
+ end
77
+
78
+ b2.use SSHRun
79
+ end
80
+ end
81
+ end
82
+
83
+ # This action is called to bring the box up from nothing.
84
+ def self.action_up
85
+ Vagrant::Action::Builder.new.tap do |b|
86
+ b.use ConfigValidate
87
+ b.use Call, IsCreated do |env, b2|
88
+ if env[:result]
89
+ b2.use MessageAlreadyCreated
90
+ next
91
+ end
92
+
93
+ b2.use TimedProvision
94
+ b2.use RunInstance
95
+ end
96
+ end
97
+ end
98
+
99
+ # The autoload farm
100
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
101
+ autoload :IsCreated, action_root.join("is_created")
102
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
103
+ autoload :MessageNotCreated, action_root.join("message_not_created")
104
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
105
+ autoload :ReadState, action_root.join("read_state")
106
+ autoload :RunInstance, action_root.join("run_instance")
107
+ autoload :TimedProvision, action_root.join("timed_provision")
108
+ autoload :TerminateInstance, action_root.join("terminate_instance")
109
+ end
110
+ end
111
+ end
@@ -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,38 @@
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
+ output = %x{ #{machine.provider_config.script} ssh-info #{machine.id} }
25
+ if $?.to_i > 0
26
+ raise Errors::ShellError, :message => "Failure: #{env[:machine].provider_config.script} ssh-info #{machine.id}"
27
+ end
28
+
29
+ host,port = output.split(/\s+/)[0,2] # TODO check formatting
30
+ return {
31
+ :host => host,
32
+ :port => port
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
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
+ output = %x{ #{machine.provider_config.script} read-state #{machine.id} }
25
+ if $?.to_i > 0
26
+ raise Errors::ShellError, :message => "Failure: #{env[:machine].provider_config.script} read-state #{machine.id}"
27
+ end
28
+ output.strip
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,110 @@
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
+ image = provider_config.image
27
+ user_data = provider_config.user_data
28
+ run_args = provider_config.run_args
29
+
30
+ # Launch!
31
+ env[:ui].info(I18n.t("vagrant_shell.launching_instance"))
32
+ env[:ui].info(" -- Image: #{image}")
33
+
34
+ # Immediately save the ID since it is created at this point.
35
+ output = %x{ #{env[:machine].provider_config.script} run-instance #{image} #{run_args.join(" ")} }
36
+ if $?.to_i > 0
37
+ raise Errors::ShellError, :message => "Failure: #{env[:machine].provider_config.script} run-instance #{image} ..."
38
+ end
39
+
40
+ env[:machine].id = output.split(/\s+/)[0]
41
+
42
+ # Wait for the instance to be ready first
43
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
44
+ tries = provider_config.instance_ready_timeout / 2
45
+
46
+ env[:ui].info(I18n.t("vagrant_shell.waiting_for_ready"))
47
+ begin
48
+ retryable(:on => Shell::Errors::TimeoutError, :tries => tries) do
49
+ # If we're interrupted don't worry about waiting
50
+ next if env[:interrupted]
51
+
52
+ # Wait for the server to be ready
53
+ true
54
+ end
55
+ rescue Shell::Errors::TimeoutError
56
+ # Delete the instance
57
+ terminate(env)
58
+
59
+ # Notify the user
60
+ raise Errors::InstanceReadyTimeout,
61
+ timeout: provider_config.instance_ready_timeout
62
+ end
63
+ end
64
+
65
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
66
+
67
+ if !env[:interrupted]
68
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
69
+ # Wait for SSH to be ready.
70
+ env[:ui].info(I18n.t("vagrant_shell.waiting_for_ssh"))
71
+ while true
72
+ # If we're interrupted then just back out
73
+ break if env[:interrupted]
74
+ break if env[:machine].communicate.ready?
75
+ sleep 2
76
+ end
77
+ end
78
+
79
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
80
+
81
+ # Ready and booted!
82
+ env[:ui].info(I18n.t("vagrant_shell.ready"))
83
+ end
84
+
85
+ # Terminate the instance if we were interrupted
86
+ terminate(env) if env[:interrupted]
87
+
88
+ @app.call(env)
89
+ end
90
+
91
+ def recover(env)
92
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
93
+
94
+ if env[:machine].provider.state.id != :not_created
95
+ # Undo the import
96
+ terminate(env)
97
+ end
98
+ end
99
+
100
+ def terminate(env)
101
+ destroy_env = env.dup
102
+ destroy_env.delete(:interrupted)
103
+ destroy_env[:config_validate] = false
104
+ destroy_env[:force_confirm_destroy] = true
105
+ env[:action_runner].run(Action.action_destroy, destroy_env)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,30 @@
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
+ output = %x{ #{env[:machine].provider_config.script} terminate-instance #{env[:machine].id}}
17
+ if $?.to_i > 0
18
+ raise Errors::ShellError, :message => "Failure: #{env[:machine].provider_config.script} terminate-instance #{env[:machine].id}"
19
+ end
20
+
21
+ puts output
22
+
23
+ env[:machine].id = nil
24
+
25
+ @app.call(env)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ 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,95 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module Shell
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The ID of the Image to use.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :image
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
+ # The shell script run-instance args
27
+ #
28
+ # @return [String]
29
+ attr_accessor :run_args
30
+
31
+ def initialize
32
+ @image = UNSET_VALUE
33
+ @instance_ready_timeout = UNSET_VALUE
34
+ @user_data = UNSET_VALUE
35
+ @script = UNSET_VALUE
36
+ @run_args = UNSET_VALUE
37
+
38
+ # Internal state (prefix with __ so they aren't automatically
39
+ # merged)
40
+ @__finalized = false
41
+ end
42
+
43
+ #-------------------------------------------------------------------
44
+ # Internal methods.
45
+ #-------------------------------------------------------------------
46
+
47
+ def merge(other)
48
+ super.tap do |result|
49
+ end
50
+ end
51
+
52
+ def finalize!
53
+ # Image must be nil, since we can't default that
54
+ @image = nil if @image == UNSET_VALUE
55
+
56
+ # Set the default timeout for waiting for an instance to be ready
57
+ @instance_ready_timeout = 120 if @instance_ready_timeout == UNSET_VALUE
58
+
59
+ # User Data is nil by default
60
+ @user_data = nil if @user_data == UNSET_VALUE
61
+
62
+ # No default shell script
63
+ @script = nil if @script == UNSET_VALUE
64
+
65
+ # No rub args by default
66
+ @run_args = [] if @run_args == UNSET_VALUE
67
+
68
+ # Mark that we finalized
69
+ @__finalized = true
70
+ end
71
+
72
+ def validate(machine)
73
+ { "Shell Provider" => [ ] }
74
+ end
75
+
76
+ # utilities
77
+ def read_script pth_script
78
+ File.read(pth_script).split(/[ \t]*[\r\n]+/).join("; ")
79
+ end
80
+
81
+ def find_script name
82
+ try_path = ENV['PATH'].split(/:/).flatten.inject([]) { |acc, p| x = File.join(p,"shell-#{name.to_s}"); File.exists?(x) && acc << x; acc }.first
83
+ if try_path
84
+ return try_path
85
+ end
86
+
87
+ try_load = $:.inject([]) { |acc, p| x = File.expand_path("../libexec/shell-#{name.to_s}", p); File.exists?(x) && acc << x; acc }.first
88
+ if try_load
89
+ return try_load
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,27 @@
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
+ end
26
+ end
27
+ end
@@ -0,0 +1,77 @@
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
+ def self.make_provider nm_provider
23
+ config(nm_provider, :provider) do
24
+ require_relative "config"
25
+ Config
26
+ end
27
+
28
+ provider(nm_provider) do
29
+ # Setup logging and i18n
30
+ setup_logging
31
+ setup_i18n
32
+
33
+ # Return the provider
34
+ require_relative "provider"
35
+ Provider
36
+ end
37
+ end
38
+
39
+ make_provider(:shell)
40
+
41
+ # This initializes the internationalization strings.
42
+ def self.setup_i18n
43
+ I18n.load_path << File.expand_path("locales/en.yml", Shell.source_root)
44
+ I18n.reload!
45
+ end
46
+
47
+ # This sets up our log level to be whatever VAGRANT_LOG is.
48
+ def self.setup_logging
49
+ require "log4r"
50
+
51
+ level = nil
52
+ begin
53
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
54
+ rescue NameError
55
+ # This means that the logging constant wasn't found,
56
+ # which is fine. We just keep `level` as `nil`. But
57
+ # we tell the user.
58
+ level = nil
59
+ end
60
+
61
+ # Some constants, such as "true" resolve to booleans, so the
62
+ # above error checking doesn't catch it. This will check to make
63
+ # sure that the log level is an integer, as Log4r requires.
64
+ level = nil if !level.is_a?(Integer)
65
+
66
+ # Set the logging level on all "vagrant" namespaced
67
+ # logs as long as we have a valid level.
68
+ if level
69
+ logger = Log4r::Logger.new("vagrant_shell")
70
+ logger.outputters = Log4r::Outputter.stderr
71
+ logger.level = level
72
+ logger = nil
73
+ end
74
+ end
75
+ end
76
+ end
77
+ 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,23 @@
1
+ # fool vagrant into using ssh-agent keys instead of a fixed key on file
2
+ module Vagrant
3
+ module Util
4
+ class Platform
5
+ def self.solaris?
6
+ true
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require "net/ssh"
13
+
14
+ module Net::SSH
15
+ class << self
16
+ alias_method :old_start, :start
17
+
18
+ def start(host, username, opts)
19
+ opts[:keys_only] = false
20
+ self.old_start(host, username, opts)
21
+ end
22
+ end
23
+ 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 = File.read(File.expand_path("../../../VERSION", __FILE__)).strip
4
+ end
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-shell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.11
4
+ version: 0.2.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -20,6 +20,22 @@ executables: []
20
20
  extensions: []
21
21
  extra_rdoc_files: []
22
22
  files:
23
+ - lib/vagrant-shell/action/is_created.rb
24
+ - lib/vagrant-shell/action/message_already_created.rb
25
+ - lib/vagrant-shell/action/message_not_created.rb
26
+ - lib/vagrant-shell/action/read_ssh_info.rb
27
+ - lib/vagrant-shell/action/read_state.rb
28
+ - lib/vagrant-shell/action/run_instance.rb
29
+ - lib/vagrant-shell/action/terminate_instance.rb
30
+ - lib/vagrant-shell/action/timed_provision.rb
31
+ - lib/vagrant-shell/action.rb
32
+ - lib/vagrant-shell/config.rb
33
+ - lib/vagrant-shell/errors.rb
34
+ - lib/vagrant-shell/plugin.rb
35
+ - lib/vagrant-shell/provider.rb
36
+ - lib/vagrant-shell/ssh-agent.rb
37
+ - lib/vagrant-shell/util/timer.rb
38
+ - lib/vagrant-shell/version.rb
23
39
  - lib/vagrant-shell.rb
24
40
  - locales/en.yml
25
41
  - CHANGELOG.md