vagrant-aws-mscottford 0.8.0

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +96 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE +8 -0
  7. data/README.md +328 -0
  8. data/Rakefile +22 -0
  9. data/cortex.yaml +15 -0
  10. data/dummy.box +0 -0
  11. data/example_box/README.md +13 -0
  12. data/example_box/metadata.json +3 -0
  13. data/lib/vagrant-aws/action/connect_aws.rb +51 -0
  14. data/lib/vagrant-aws/action/elb_deregister_instance.rb +24 -0
  15. data/lib/vagrant-aws/action/elb_register_instance.rb +24 -0
  16. data/lib/vagrant-aws/action/is_created.rb +18 -0
  17. data/lib/vagrant-aws/action/is_stopped.rb +18 -0
  18. data/lib/vagrant-aws/action/message_already_created.rb +16 -0
  19. data/lib/vagrant-aws/action/message_not_created.rb +16 -0
  20. data/lib/vagrant-aws/action/message_will_not_destroy.rb +16 -0
  21. data/lib/vagrant-aws/action/package_instance.rb +192 -0
  22. data/lib/vagrant-aws/action/read_ssh_info.rb +53 -0
  23. data/lib/vagrant-aws/action/read_state.rb +38 -0
  24. data/lib/vagrant-aws/action/run_instance.rb +311 -0
  25. data/lib/vagrant-aws/action/start_instance.rb +81 -0
  26. data/lib/vagrant-aws/action/stop_instance.rb +28 -0
  27. data/lib/vagrant-aws/action/terminate_instance.rb +51 -0
  28. data/lib/vagrant-aws/action/timed_provision.rb +21 -0
  29. data/lib/vagrant-aws/action/wait_for_state.rb +41 -0
  30. data/lib/vagrant-aws/action/warn_networks.rb +19 -0
  31. data/lib/vagrant-aws/action.rb +209 -0
  32. data/lib/vagrant-aws/cap/winrm_info.rb +46 -0
  33. data/lib/vagrant-aws/config.rb +577 -0
  34. data/lib/vagrant-aws/errors.rb +43 -0
  35. data/lib/vagrant-aws/plugin.rb +78 -0
  36. data/lib/vagrant-aws/provider.rb +50 -0
  37. data/lib/vagrant-aws/util/elb.rb +58 -0
  38. data/lib/vagrant-aws/util/timer.rb +17 -0
  39. data/lib/vagrant-aws/version.rb +5 -0
  40. data/lib/vagrant-aws.rb +18 -0
  41. data/locales/en.yml +159 -0
  42. data/spec/spec_helper.rb +1 -0
  43. data/spec/vagrant-aws/config_spec.rb +374 -0
  44. data/templates/metadata.json.erb +3 -0
  45. data/templates/vagrant-aws_package_Vagrantfile.erb +5 -0
  46. data/vagrant-aws-mscottford.gemspec +64 -0
  47. metadata +177 -0
@@ -0,0 +1,81 @@
1
+ require "log4r"
2
+
3
+ require 'vagrant/util/retryable'
4
+
5
+ require 'vagrant-aws/util/timer'
6
+
7
+ module VagrantPlugins
8
+ module AWS
9
+ module Action
10
+ # This starts a stopped instance.
11
+ class StartInstance
12
+ include Vagrant::Util::Retryable
13
+
14
+ def initialize(app, env)
15
+ @app = app
16
+ @logger = Log4r::Logger.new("vagrant_aws::action::start_instance")
17
+ end
18
+
19
+ def call(env)
20
+ # Initialize metrics if they haven't been
21
+ env[:metrics] ||= {}
22
+
23
+ server = env[:aws_compute].servers.get(env[:machine].id)
24
+
25
+ env[:ui].info(I18n.t("vagrant_aws.starting"))
26
+
27
+ begin
28
+ server.start
29
+
30
+ region = env[:machine].provider_config.region
31
+ region_config = env[:machine].provider_config.get_region_config(region)
32
+
33
+ # Wait for the instance to be ready first
34
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
35
+ tries = region_config.instance_ready_timeout / 2
36
+
37
+ env[:ui].info(I18n.t("vagrant_aws.waiting_for_ready"))
38
+ begin
39
+ retryable(:on => Fog::Errors::TimeoutError, :tries => tries) do
40
+ # If we're interrupted don't worry about waiting
41
+ next if env[:interrupted]
42
+
43
+ # Wait for the server to be ready
44
+ server.wait_for(2) { ready? }
45
+ end
46
+ rescue Fog::Errors::TimeoutError
47
+ # Notify the user
48
+ raise Errors::InstanceReadyTimeout,
49
+ timeout: region_config.instance_ready_timeout
50
+ end
51
+ end
52
+ rescue Fog::Compute::AWS::Error => e
53
+ raise Errors::FogError, :message => e.message
54
+ end
55
+
56
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
57
+
58
+ if !env[:interrupted]
59
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
60
+ # Wait for SSH to be ready.
61
+ env[:ui].info(I18n.t("vagrant_aws.waiting_for_ssh"))
62
+ while true
63
+ # If we're interrupted then just back out
64
+ break if env[:interrupted]
65
+ break if env[:machine].communicate.ready?
66
+ sleep 2
67
+ end
68
+ end
69
+
70
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
71
+
72
+ # Ready and booted!
73
+ env[:ui].info(I18n.t("vagrant_aws.ready"))
74
+ end
75
+
76
+ @app.call(env)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module AWS
5
+ module Action
6
+ # This stops the running instance.
7
+ class StopInstance
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new("vagrant_aws::action::stop_instance")
11
+ end
12
+
13
+ def call(env)
14
+ server = env[:aws_compute].servers.get(env[:machine].id)
15
+
16
+ if env[:machine].state.id == :stopped
17
+ env[:ui].info(I18n.t("vagrant_aws.already_status", :status => env[:machine].state.id))
18
+ else
19
+ env[:ui].info(I18n.t("vagrant_aws.stopping"))
20
+ server.stop(!!env[:force_halt])
21
+ end
22
+
23
+ @app.call(env)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ require "log4r"
2
+ require "json"
3
+
4
+ module VagrantPlugins
5
+ module AWS
6
+ module Action
7
+ # This terminates the running instance.
8
+ class TerminateInstance
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new("vagrant_aws::action::terminate_instance")
12
+ end
13
+
14
+ def call(env)
15
+ server = env[:aws_compute].servers.get(env[:machine].id)
16
+ region = env[:machine].provider_config.region
17
+ region_config = env[:machine].provider_config.get_region_config(region)
18
+
19
+ elastic_ip = region_config.elastic_ip
20
+
21
+ # Release the elastic IP
22
+ ip_file = env[:machine].data_dir.join('elastic_ip')
23
+ if ip_file.file?
24
+ release_address(env,ip_file.read)
25
+ ip_file.delete
26
+ end
27
+
28
+ # Destroy the server and remove the tracking ID
29
+ env[:ui].info(I18n.t("vagrant_aws.terminating"))
30
+ server.destroy
31
+ env[:machine].id = nil
32
+
33
+ @app.call(env)
34
+ end
35
+
36
+ # Release an elastic IP address
37
+ def release_address(env,eip)
38
+ h = JSON.parse(eip)
39
+ # Use association_id and allocation_id for VPC, use public IP for EC2
40
+ if h['association_id']
41
+ env[:aws_compute].disassociate_address(nil,h['association_id'])
42
+ env[:aws_compute].release_address(h['allocation_id'])
43
+ else
44
+ env[:aws_compute].disassociate_address(h['public_ip'])
45
+ env[:aws_compute].release_address(h['public_ip'])
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ require "vagrant-aws/util/timer"
2
+
3
+ module VagrantPlugins
4
+ module AWS
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,41 @@
1
+ require "log4r"
2
+ require "timeout"
3
+
4
+ module VagrantPlugins
5
+ module AWS
6
+ module Action
7
+ # This action will wait for a machine to reach a specific state or quit by timeout
8
+ class WaitForState
9
+ # env[:result] will be false in case of timeout.
10
+ # @param [Symbol] state Target machine state.
11
+ # @param [Number] timeout Timeout in seconds.
12
+ def initialize(app, env, state, timeout)
13
+ @app = app
14
+ @logger = Log4r::Logger.new("vagrant_aws::action::wait_for_state")
15
+ @state = state
16
+ @timeout = timeout
17
+ end
18
+
19
+ def call(env)
20
+ env[:result] = true
21
+ if env[:machine].state.id == @state
22
+ @logger.info(I18n.t("vagrant_aws.already_status", :status => @state))
23
+ else
24
+ @logger.info("Waiting for machine to reach state #{@state}")
25
+ begin
26
+ Timeout.timeout(@timeout) do
27
+ until env[:machine].state.id == @state
28
+ sleep 2
29
+ end
30
+ end
31
+ rescue Timeout::Error
32
+ env[:result] = false # couldn't reach state in time
33
+ end
34
+ end
35
+
36
+ @app.call(env)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module AWS
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_aws.warn_networks"))
12
+ end
13
+
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,209 @@
1
+ require "pathname"
2
+
3
+ require "vagrant/action/builder"
4
+
5
+ module VagrantPlugins
6
+ module AWS
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
+ def self.action_package
12
+ Vagrant::Action::Builder.new.tap do |b|
13
+ b.use Call, IsCreated do |env, b2|
14
+ if !env[:result]
15
+ b2.use MessageNotCreated
16
+ next
17
+ end
18
+
19
+ # Connect to AWS and then Create a package from the server instance
20
+ b2.use ConnectAWS
21
+ b2.use PackageInstance
22
+ end
23
+ end
24
+ end
25
+
26
+ # This action is called to halt the remote machine.
27
+ def self.action_halt
28
+ Vagrant::Action::Builder.new.tap do |b|
29
+ b.use ConfigValidate
30
+ b.use Call, IsCreated do |env, b2|
31
+ if !env[:result]
32
+ b2.use MessageNotCreated
33
+ next
34
+ end
35
+
36
+ b2.use ConnectAWS
37
+ b2.use StopInstance
38
+ end
39
+ end
40
+ end
41
+
42
+ # This action is called to terminate the remote machine.
43
+ def self.action_destroy
44
+ Vagrant::Action::Builder.new.tap do |b|
45
+ b.use Call, DestroyConfirm do |env, b2|
46
+ if env[:result]
47
+ b2.use ConfigValidate
48
+ b2.use Call, IsCreated do |env2, b3|
49
+ if !env2[:result]
50
+ b3.use MessageNotCreated
51
+ next
52
+ end
53
+ b3.use ConnectAWS
54
+ b3.use ElbDeregisterInstance
55
+ b3.use TerminateInstance
56
+ b3.use ProvisionerCleanup if defined?(ProvisionerCleanup)
57
+ end
58
+ else
59
+ b2.use MessageWillNotDestroy
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ # This action is called when `vagrant provision` is called.
66
+ def self.action_provision
67
+ Vagrant::Action::Builder.new.tap do |b|
68
+ b.use ConfigValidate
69
+ b.use Call, IsCreated do |env, b2|
70
+ if !env[:result]
71
+ b2.use MessageNotCreated
72
+ next
73
+ end
74
+
75
+ b2.use Provision
76
+ end
77
+ end
78
+ end
79
+
80
+ # This action is called to read the SSH info of the machine. The
81
+ # resulting state is expected to be put into the `:machine_ssh_info`
82
+ # key.
83
+ def self.action_read_ssh_info
84
+ Vagrant::Action::Builder.new.tap do |b|
85
+ b.use ConfigValidate
86
+ b.use ConnectAWS
87
+ b.use ReadSSHInfo
88
+ end
89
+ end
90
+
91
+ # This action is called to read the state of the machine. The
92
+ # resulting state is expected to be put into the `:machine_state_id`
93
+ # key.
94
+ def self.action_read_state
95
+ Vagrant::Action::Builder.new.tap do |b|
96
+ b.use ConfigValidate
97
+ b.use ConnectAWS
98
+ b.use ReadState
99
+ end
100
+ end
101
+
102
+ # This action is called to SSH into the machine.
103
+ def self.action_ssh
104
+ Vagrant::Action::Builder.new.tap do |b|
105
+ b.use ConfigValidate
106
+ b.use Call, IsCreated do |env, b2|
107
+ if !env[:result]
108
+ b2.use MessageNotCreated
109
+ next
110
+ end
111
+
112
+ b2.use SSHExec
113
+ end
114
+ end
115
+ end
116
+
117
+ def self.action_ssh_run
118
+ Vagrant::Action::Builder.new.tap do |b|
119
+ b.use ConfigValidate
120
+ b.use Call, IsCreated do |env, b2|
121
+ if !env[:result]
122
+ b2.use MessageNotCreated
123
+ next
124
+ end
125
+
126
+ b2.use SSHRun
127
+ end
128
+ end
129
+ end
130
+
131
+ def self.action_prepare_boot
132
+ Vagrant::Action::Builder.new.tap do |b|
133
+ b.use Provision
134
+ b.use SyncedFolders
135
+ b.use WarnNetworks
136
+ b.use ElbRegisterInstance
137
+ end
138
+ end
139
+
140
+ # This action is called to bring the box up from nothing.
141
+ def self.action_up
142
+ Vagrant::Action::Builder.new.tap do |b|
143
+ b.use HandleBox
144
+ b.use ConfigValidate
145
+ b.use BoxCheckOutdated
146
+ b.use ConnectAWS
147
+ b.use Call, IsCreated do |env1, b1|
148
+ if env1[:result]
149
+ b1.use Call, IsStopped do |env2, b2|
150
+ if env2[:result]
151
+ b2.use action_prepare_boot
152
+ b2.use StartInstance # restart this instance
153
+ else
154
+ b2.use MessageAlreadyCreated # TODO write a better message
155
+ end
156
+ end
157
+ else
158
+ b1.use action_prepare_boot
159
+ b1.use RunInstance # launch a new instance
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ def self.action_reload
166
+ Vagrant::Action::Builder.new.tap do |b|
167
+ b.use ConfigValidate
168
+ b.use ConnectAWS
169
+ b.use Call, IsCreated do |env, b2|
170
+ if !env[:result]
171
+ b2.use MessageNotCreated
172
+ next
173
+ end
174
+
175
+ b2.use action_halt
176
+ b2.use Call, WaitForState, :stopped, 120 do |env2, b3|
177
+ if env2[:result]
178
+ b3.use action_up
179
+ else
180
+ # TODO we couldn't reach :stopped, what now?
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+
187
+ # The autoload farm
188
+ action_root = Pathname.new(File.expand_path("../action", __FILE__))
189
+ autoload :ConnectAWS, action_root.join("connect_aws")
190
+ autoload :IsCreated, action_root.join("is_created")
191
+ autoload :IsStopped, action_root.join("is_stopped")
192
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
193
+ autoload :MessageNotCreated, action_root.join("message_not_created")
194
+ autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
195
+ autoload :PackageInstance, action_root.join("package_instance")
196
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
197
+ autoload :ReadState, action_root.join("read_state")
198
+ autoload :RunInstance, action_root.join("run_instance")
199
+ autoload :StartInstance, action_root.join("start_instance")
200
+ autoload :StopInstance, action_root.join("stop_instance")
201
+ autoload :TerminateInstance, action_root.join("terminate_instance")
202
+ autoload :TimedProvision, action_root.join("timed_provision") # some plugins now expect this action to exist
203
+ autoload :WaitForState, action_root.join("wait_for_state")
204
+ autoload :WarnNetworks, action_root.join("warn_networks")
205
+ autoload :ElbRegisterInstance, action_root.join("elb_register_instance")
206
+ autoload :ElbDeregisterInstance, action_root.join("elb_deregister_instance")
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,46 @@
1
+ Vagrant.require "log4r"
2
+
3
+ require Vagrant.source_root.join("plugins/communicators/winrm/helper").to_s
4
+
5
+ module VagrantPlugins
6
+ module AWS
7
+ module Cap
8
+ module WinRMInfo
9
+ LOGGER = Log4r::Logger.new("vagrant::plugins::aws::winrm_info")
10
+
11
+ def self.winrm_info(machine)
12
+ info = {}
13
+ info[:host] = CommunicatorWinRM::Helper.winrm_address(machine)
14
+ info[:port] = CommunicatorWinRM::Helper.winrm_port(machine, info[:host] == "127.0.0.1")
15
+
16
+ if machine.config.winrm.password == :query_ec2 || machine.config.winrm.password == :query_ec2_retry
17
+ machine.ui.info("Looking up Windows password for instance #{machine.id}...") if machine.config.winrm.password != :query_ec2_retry
18
+
19
+ aws_profile = machine.provider_config.aws_profile
20
+ keypair_path = machine.provider_config.keypair_path
21
+
22
+ command = "aws ec2 get-password-data --instance-id #{machine.id} --priv-launch-key #{keypair_path} --output json"
23
+ if !aws_profile.nil? && !aws_profile.empty?
24
+ command += " --profile #{aws_profile}"
25
+ end
26
+
27
+ response = JSON.parse(`#{command}`)
28
+ machine.config.winrm.password = response["PasswordData"]
29
+
30
+ if machine.config.winrm.password.nil? || machine.config.winrm.password.empty?
31
+ machine.ui.debug("Windows password not available yet. Retrying after 30 seconds...")
32
+ sleep(30)
33
+ machine.config.winrm.password = :query_ec2_retry
34
+ raise Errors::WinRMNotReady
35
+ else
36
+ machine.ui.info("Windows password found.")
37
+ end
38
+ end
39
+
40
+ info
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+