vagrant-aws 0.0.1 → 0.1.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 (56) hide show
  1. data/.gitignore +11 -2
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile +8 -2
  4. data/LICENSE +8 -0
  5. data/README.md +192 -65
  6. data/Rakefile +18 -7
  7. data/dummy.box +0 -0
  8. data/example_box/README.md +13 -0
  9. data/example_box/metadata.json +3 -0
  10. data/lib/vagrant-aws.rb +17 -13
  11. data/lib/vagrant-aws/action.rb +107 -0
  12. data/lib/vagrant-aws/action/connect_aws.rb +38 -0
  13. data/lib/vagrant-aws/action/is_created.rb +18 -0
  14. data/lib/vagrant-aws/action/message_already_created.rb +16 -0
  15. data/lib/vagrant-aws/action/message_not_created.rb +16 -0
  16. data/lib/vagrant-aws/action/read_ssh_info.rb +47 -0
  17. data/lib/vagrant-aws/action/read_state.rb +38 -0
  18. data/lib/vagrant-aws/action/run_instance.rb +148 -0
  19. data/lib/vagrant-aws/action/sync_folders.rb +57 -0
  20. data/lib/vagrant-aws/action/terminate_instance.rb +26 -0
  21. data/lib/vagrant-aws/action/timed_provision.rb +21 -0
  22. data/lib/vagrant-aws/action/warn_networks.rb +19 -0
  23. data/lib/vagrant-aws/config.rb +253 -38
  24. data/lib/vagrant-aws/errors.rb +15 -25
  25. data/lib/vagrant-aws/plugin.rb +73 -0
  26. data/lib/vagrant-aws/provider.rb +50 -0
  27. data/lib/vagrant-aws/util/timer.rb +17 -0
  28. data/lib/vagrant-aws/version.rb +4 -2
  29. data/locales/en.yml +65 -61
  30. data/spec/vagrant-aws/config_spec.rb +161 -0
  31. data/vagrant-aws.gemspec +54 -25
  32. metadata +79 -86
  33. data/lib/vagrant-aws/action/create.rb +0 -56
  34. data/lib/vagrant-aws/action/create_image.rb +0 -106
  35. data/lib/vagrant-aws/action/create_sshkey.rb +0 -39
  36. data/lib/vagrant-aws/action/deregister_image.rb +0 -27
  37. data/lib/vagrant-aws/action/populate_ssh.rb +0 -41
  38. data/lib/vagrant-aws/action/prepare_provisioners.rb +0 -127
  39. data/lib/vagrant-aws/action/resume.rb +0 -20
  40. data/lib/vagrant-aws/action/suspend.rb +0 -20
  41. data/lib/vagrant-aws/action/terminate.rb +0 -21
  42. data/lib/vagrant-aws/box.rb +0 -20
  43. data/lib/vagrant-aws/box_collection.rb +0 -15
  44. data/lib/vagrant-aws/command.rb +0 -186
  45. data/lib/vagrant-aws/environment.rb +0 -79
  46. data/lib/vagrant-aws/middleware.rb +0 -53
  47. data/lib/vagrant-aws/system.rb +0 -24
  48. data/lib/vagrant-aws/vm.rb +0 -94
  49. data/lib/vagrant_init.rb +0 -4
  50. data/test/test_helper.rb +0 -24
  51. data/test/vagrant-aws/action/create_image_test.rb +0 -63
  52. data/test/vagrant-aws/action/create_ssh_key_test.rb +0 -43
  53. data/test/vagrant-aws/action/create_test.rb +0 -65
  54. data/test/vagrant-aws/action/terminate_test.rb +0 -20
  55. data/test/vagrant-aws/command_test.rb +0 -21
  56. data/test/vagrant-aws/config_test.rb +0 -14
@@ -0,0 +1,38 @@
1
+ require "fog"
2
+ require "log4r"
3
+
4
+ module VagrantPlugins
5
+ module AWS
6
+ module Action
7
+ # This action connects to AWS, verifies credentials work, and
8
+ # puts the AWS connection object into the `:aws_compute` key
9
+ # in the environment.
10
+ class ConnectAWS
11
+ def initialize(app, env)
12
+ @app = app
13
+ @logger = Log4r::Logger.new("vagrant_aws::action::connect_aws")
14
+ end
15
+
16
+ def call(env)
17
+ # Get the region we're going to booting up in
18
+ region = env[:machine].provider_config.region
19
+
20
+ # Get the configs
21
+ region_config = env[:machine].provider_config.get_region_config(region)
22
+ access_key_id = region_config.access_key_id
23
+ secret_access_key = region_config.secret_access_key
24
+
25
+ @logger.info("Connecting to AWS...")
26
+ env[:aws_compute] = Fog::Compute.new({
27
+ :provider => :aws,
28
+ :aws_access_key_id => access_key_id,
29
+ :aws_secret_access_key => secret_access_key,
30
+ :region => region
31
+ })
32
+
33
+ @app.call(env)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module AWS
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 AWS
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_aws.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 AWS
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_aws.not_created"))
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module AWS
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_aws::action::read_ssh_info")
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_ssh_info] = read_ssh_info(env[:aws_compute], env[:machine])
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def read_ssh_info(aws, machine)
21
+ return nil if machine.id.nil?
22
+
23
+ # Find the machine
24
+ server = aws.servers.get(machine.id)
25
+ if server.nil?
26
+ # The machine can't be found
27
+ @logger.info("Machine couldn't be found, assuming it got destroyed.")
28
+ machine.id = nil
29
+ return nil
30
+ end
31
+
32
+ # Get the configuration
33
+ region = machine.provider_config.region
34
+ config = machine.provider_config.get_region_config(region)
35
+
36
+ # Read the DNS info
37
+ return {
38
+ :host => server.dns_name,
39
+ :port => 22,
40
+ :private_key_path => config.ssh_private_key_path,
41
+ :username => config.ssh_username
42
+ }
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,38 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module AWS
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_aws::action::read_state")
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_state_id] = read_state(env[:aws_compute], env[:machine])
16
+
17
+ @app.call(env)
18
+ end
19
+
20
+ def read_state(aws, machine)
21
+ return :not_created if machine.id.nil?
22
+
23
+ # Find the machine
24
+ server = aws.servers.get(machine.id)
25
+ if server.nil? || [:"shutting-down", :terminated].include?(server.state.to_sym)
26
+ # The machine can't be found
27
+ @logger.info("Machine not found or terminated, assuming it got destroyed.")
28
+ machine.id = nil
29
+ return :not_created
30
+ end
31
+
32
+ # Return the state
33
+ return server.state.to_sym
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,148 @@
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 runs the configured instance.
11
+ class RunInstance
12
+ include Vagrant::Util::Retryable
13
+
14
+ def initialize(app, env)
15
+ @app = app
16
+ @logger = Log4r::Logger.new("vagrant_aws::action::run_instance")
17
+ end
18
+
19
+ def call(env)
20
+ # Initialize metrics if they haven't been
21
+ env[:metrics] ||= {}
22
+
23
+ # Get the region we're going to booting up in
24
+ region = env[:machine].provider_config.region
25
+
26
+ # Get the configs
27
+ region_config = env[:machine].provider_config.get_region_config(region)
28
+ ami = region_config.ami
29
+ availability_zone = region_config.availability_zone
30
+ instance_type = region_config.instance_type
31
+ keypair = region_config.keypair_name
32
+ private_ip_address = region_config.private_ip_address
33
+ security_groups = region_config.security_groups
34
+ subnet_id = region_config.subnet_id
35
+ tags = region_config.tags
36
+
37
+ # If there is no keypair then warn the user
38
+ if !keypair
39
+ env[:ui].warn(I18n.t("vagrant_aws.launch_no_keypair"))
40
+ end
41
+
42
+ # If there is a subnet ID then warn the user
43
+ if subnet_id
44
+ env[:ui].warn(I18n.t("vagrant_aws.launch_vpc_warning"))
45
+ end
46
+
47
+ # Launch!
48
+ env[:ui].info(I18n.t("vagrant_aws.launching_instance"))
49
+ env[:ui].info(" -- Type: #{instance_type}")
50
+ env[:ui].info(" -- AMI: #{ami}")
51
+ env[:ui].info(" -- Region: #{region}")
52
+ env[:ui].info(" -- Availability Zone: #{availability_zone}") if availability_zone
53
+ env[:ui].info(" -- Keypair: #{keypair}") if keypair
54
+ env[:ui].info(" -- Subnet ID: #{subnet_id}") if subnet_id
55
+ env[:ui].info(" -- Private IP: #{private_ip_address}") if private_ip_address
56
+ env[:ui].info(" -- Security Groups: #{security_groups.inspect}") if !security_groups.empty?
57
+
58
+ begin
59
+ options = {
60
+ :availability_zone => availability_zone,
61
+ :flavor_id => instance_type,
62
+ :image_id => ami,
63
+ :key_name => keypair,
64
+ :private_ip_address => private_ip_address,
65
+ :subnet_id => subnet_id,
66
+ :tags => tags
67
+ }
68
+
69
+ if !security_groups.empty?
70
+ security_group_key = options[:subnet_id].nil? ? :groups : :security_group_ids
71
+ options[security_group_key] = security_groups
72
+ end
73
+
74
+ server = env[:aws_compute].servers.create(options)
75
+ rescue Fog::Compute::AWS::NotFound => e
76
+ # Invalid subnet doesn't have its own error so we catch and
77
+ # check the error message here.
78
+ if e.message =~ /subnet ID/
79
+ raise Errors::FogError,
80
+ :message => "Subnet ID not found: #{subnet_id}"
81
+ end
82
+
83
+ raise
84
+ rescue Fog::Compute::AWS::Error => e
85
+ raise Errors::FogError, :message => e.message
86
+ end
87
+
88
+ # Immediately save the ID since it is created at this point.
89
+ env[:machine].id = server.id
90
+
91
+ # Wait for the instance to be ready first
92
+ env[:metrics]["instance_ready_time"] = Util::Timer.time do
93
+ env[:ui].info(I18n.t("vagrant_aws.waiting_for_ready"))
94
+ retryable(:on => Fog::Errors::TimeoutError, :tries => 30) do
95
+ # If we're interrupted don't worry about waiting
96
+ next if env[:interrupted]
97
+
98
+ # Wait for the server to be ready
99
+ server.wait_for(2) { ready? }
100
+ end
101
+ end
102
+
103
+ @logger.info("Time to instance ready: #{env[:metrics]["instance_ready_time"]}")
104
+
105
+ if !env[:interrupted]
106
+ env[:metrics]["instance_ssh_time"] = Util::Timer.time do
107
+ # Wait for SSH to be ready.
108
+ env[:ui].info(I18n.t("vagrant_aws.waiting_for_ssh"))
109
+ while true
110
+ # If we're interrupted then just back out
111
+ break if env[:interrupted]
112
+ break if env[:machine].communicate.ready?
113
+ sleep 2
114
+ end
115
+ end
116
+
117
+ @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
118
+
119
+ # Ready and booted!
120
+ env[:ui].info(I18n.t("vagrant_aws.ready"))
121
+ end
122
+
123
+ # Terminate the instance if we were interrupted
124
+ terminate(env) if env[:interrupted]
125
+
126
+ @app.call(env)
127
+ end
128
+
129
+ def recover(env)
130
+ return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
131
+
132
+ if env[:machine].provider.state.id != :not_created
133
+ # Undo the import
134
+ terminate(env)
135
+ end
136
+ end
137
+
138
+ def terminate(env)
139
+ destroy_env = env.dup
140
+ destroy_env.delete(:interrupted)
141
+ destroy_env[:config_validate] = false
142
+ destroy_env[:force_confirm_destroy] = true
143
+ env[:action_runner].run(Action.action_destroy, destroy_env)
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,57 @@
1
+ require "log4r"
2
+
3
+ require "vagrant/util/subprocess"
4
+
5
+ module VagrantPlugins
6
+ module AWS
7
+ module Action
8
+ # This middleware uses `rsync` to sync the folders over to the
9
+ # AWS instance.
10
+ class SyncFolders
11
+ def initialize(app, env)
12
+ @app = app
13
+ @logger = Log4r::Logger.new("vagrant_aws::action::sync_folders")
14
+ end
15
+
16
+ def call(env)
17
+ @app.call(env)
18
+
19
+ ssh_info = env[:machine].ssh_info
20
+
21
+ env[:machine].config.vm.synced_folders.each do |id, data|
22
+ hostpath = File.expand_path(data[:hostpath], env[:root_path])
23
+ guestpath = data[:guestpath]
24
+
25
+ # Make sure there is a trailing slash on the host path to
26
+ # avoid creating an additional directory with rsync
27
+ hostpath = "#{hostpath}/" if hostpath !~ /\/$/
28
+
29
+ env[:ui].info(I18n.t("vagrant_aws.rsync_folder",
30
+ :hostpath => hostpath,
31
+ :guestpath => guestpath))
32
+
33
+ # Create the guest path
34
+ env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
35
+ env[:machine].communicate.sudo(
36
+ "chown #{ssh_info[:username]} '#{guestpath}'")
37
+
38
+ # Rsync over to the guest path using the SSH info
39
+ command = [
40
+ "rsync", "--verbose", "--archive", "-z",
41
+ "-e", "ssh -p #{ssh_info[:port]} -i '#{ssh_info[:private_key_path]}'",
42
+ hostpath,
43
+ "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
44
+
45
+ r = Vagrant::Util::Subprocess.execute(*command)
46
+ if r.exit_code != 0
47
+ raise Errors::RsyncError,
48
+ :guestpath => guestpath,
49
+ :hostpath => hostpath,
50
+ :stderr => r.stderr
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,26 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module AWS
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_aws::action::run_instance")
11
+ end
12
+
13
+ def call(env)
14
+ server = env[:aws_compute].servers.get(env[:machine].id)
15
+
16
+ # Destroy the server and remove the tracking ID
17
+ env[:ui].info(I18n.t("vagrant_aws.terminating"))
18
+ server.destroy
19
+ env[:machine].id = nil
20
+
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ 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, 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"] << [p.class.to_s, timer]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ 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