vagrant-aws 0.0.1 → 0.1.0

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