vagrant-shell 0.2.11 → 0.2.12

Sign up to get free protection for your applications and to get access to all the features.
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