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
@@ -1,38 +1,253 @@
1
- module VagrantAWS
2
- # A configuration class to configure defaults which are used for
3
- # the `vagrant-aws` plugin.
4
- class Config < Vagrant::Config::Base
5
- configures :aws
6
-
7
- attr_accessor :key_name
8
- attr_writer :private_key_path
9
- attr_accessor :username
10
- attr_accessor :security_groups
11
-
12
- attr_accessor :image
13
- attr_accessor :flavor
14
-
15
- attr_accessor :region
16
- attr_accessor :availability_zone
17
-
18
- def initialize
19
- @security_groups = ["default"]
20
- @region = "us-east-1"
21
- @username = "ubuntu"
22
- @image = "ami-2ec83147"
23
- @flavor = "t1.micro"
24
- end
25
-
26
- def using?
27
- return top.env.is_a?(VagrantAWS::Environment)
28
- end
29
-
30
- def private_key_path
31
- @private_key_path.nil? ? nil : File.expand_path(@private_key_path)
32
- end
33
-
34
- def validate(errors)
35
- errors.add(I18n.t("vagrant.config.ssh.private_key_missing", :path => private_key_path)) if private_key_path && !File.exists?(private_key_path)
36
- end
37
- end
38
- end
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module AWS
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The access key ID for accessing AWS.
7
+ #
8
+ # @return [String]
9
+ attr_accessor :access_key_id
10
+
11
+ # The ID of the AMI to use.
12
+ #
13
+ # @return [String]
14
+ attr_accessor :ami
15
+
16
+ # The availability zone to launch the instance into. If nil, it will
17
+ # use the default for your account.
18
+ #
19
+ # @return [String]
20
+ attr_accessor :availability_zone
21
+
22
+ # The type of instance to launch, such as "m1.small"
23
+ #
24
+ # @return [String]
25
+ attr_accessor :instance_type
26
+
27
+ # The name of the keypair to use.
28
+ #
29
+ # @return [String]
30
+ attr_accessor :keypair_name
31
+
32
+ # The private IP address to give this machine (VPC).
33
+ #
34
+ # @return [String]
35
+ attr_accessor :private_ip_address
36
+
37
+ # The name of the AWS region in which to create the instance.
38
+ #
39
+ # @return [String]
40
+ attr_accessor :region
41
+
42
+ # The secret access key for accessing AWS.
43
+ #
44
+ # @return [String]
45
+ attr_accessor :secret_access_key
46
+
47
+ # The security groups to set on the instance. For VPC this must
48
+ # be a list of IDs. For EC2, it can be either.
49
+ #
50
+ # @return [Array<String>]
51
+ attr_accessor :security_groups
52
+
53
+ # The path to the SSH private key to use with this EC2 instance.
54
+ # This overrides the `config.ssh.private_key_path` variable.
55
+ #
56
+ # @return [String]
57
+ attr_accessor :ssh_private_key_path
58
+
59
+ # The SSH username to use with this EC2 instance. This overrides
60
+ # the `config.ssh.username` variable.
61
+ #
62
+ # @return [String]
63
+ attr_accessor :ssh_username
64
+
65
+ # The subnet ID to launch the machine into (VPC).
66
+ #
67
+ # @return [String]
68
+ attr_accessor :subnet_id
69
+
70
+ # The tags for the machine.
71
+ #
72
+ # @return [Hash<String, String>]
73
+ attr_accessor :tags
74
+
75
+ def initialize(region_specific=false)
76
+ @access_key_id = UNSET_VALUE
77
+ @ami = UNSET_VALUE
78
+ @availability_zone = UNSET_VALUE
79
+ @instance_type = UNSET_VALUE
80
+ @keypair_name = UNSET_VALUE
81
+ @private_ip_address = UNSET_VALUE
82
+ @region = UNSET_VALUE
83
+ @secret_access_key = UNSET_VALUE
84
+ @security_groups = UNSET_VALUE
85
+ @ssh_private_key_path = UNSET_VALUE
86
+ @ssh_username = UNSET_VALUE
87
+ @subnet_id = UNSET_VALUE
88
+ @tags = {}
89
+
90
+ # Internal state (prefix with __ so they aren't automatically
91
+ # merged)
92
+ @__compiled_region_configs = {}
93
+ @__finalized = false
94
+ @__region_config = {}
95
+ @__region_specific = region_specific
96
+ end
97
+
98
+ # Allows region-specific overrides of any of the settings on this
99
+ # configuration object. This allows the user to override things like
100
+ # AMI and keypair name for regions. Example:
101
+ #
102
+ # aws.region_config "us-east-1" do |region|
103
+ # region.ami = "ami-12345678"
104
+ # region.keypair_name = "company-east"
105
+ # end
106
+ #
107
+ # @param [String] region The region name to configure.
108
+ # @param [Hash] attributes Direct attributes to set on the configuration
109
+ # as a shortcut instead of specifying a full block.
110
+ # @yield [config] Yields a new AWS configuration.
111
+ def region_config(region, attributes=nil, &block)
112
+ # Append the block to the list of region configs for that region.
113
+ # We'll evaluate these upon finalization.
114
+ @__region_config[region] ||= []
115
+
116
+ # Append a block that sets attributes if we got one
117
+ if attributes
118
+ attr_block = lambda do |config|
119
+ config.set_options(attributes)
120
+ end
121
+
122
+ @__region_config[region] << attr_block
123
+ end
124
+
125
+ # Append a block if we got one
126
+ @__region_config[region] << block if block_given?
127
+ end
128
+
129
+ #-------------------------------------------------------------------
130
+ # Internal methods.
131
+ #-------------------------------------------------------------------
132
+
133
+ def merge(other)
134
+ super.tap do |result|
135
+ # Copy over the region specific flag. "True" is retained if either
136
+ # has it.
137
+ new_region_specific = other.instance_variable_get(:@__region_specific)
138
+ result.instance_variable_set(
139
+ :@__region_specific, new_region_specific || @__region_specific)
140
+
141
+ # Go through all the region configs and prepend ours onto
142
+ # theirs.
143
+ new_region_config = other.instance_variable_get(:@__region_config)
144
+ @__region_config.each do |key, value|
145
+ new_region_config[key] ||= []
146
+ new_region_config[key] = value + new_region_config[key]
147
+ end
148
+
149
+ # Set it
150
+ result.instance_variable_set(:@__region_config, new_region_config)
151
+
152
+ # Merge in the tags
153
+ result.tags.merge!(self.tags)
154
+ result.tags.merge!(other.tags)
155
+ end
156
+ end
157
+
158
+ def finalize!
159
+ # The access keys default to nil
160
+ @access_key_id = nil if @access_key_id == UNSET_VALUE
161
+ @secret_access_key = nil if @secret_access_key == UNSET_VALUE
162
+
163
+ # AMI must be nil, since we can't default that
164
+ @ami = nil if @ami == UNSET_VALUE
165
+
166
+ # Default instance type is an m1.small
167
+ @instance_type = "m1.small" if @instance_type == UNSET_VALUE
168
+
169
+ # Keypair defaults to nil
170
+ @keypair_name = nil if @keypair_name == UNSET_VALUE
171
+
172
+ # Default the private IP to nil since VPC is not default
173
+ @private_ip_address = nil if @private_ip_address == UNSET_VALUE
174
+
175
+ # Default region is us-east-1. This is sensible because AWS
176
+ # generally defaults to this as well.
177
+ @region = "us-east-1" if @region == UNSET_VALUE
178
+ @availability_zone = nil if @availability_zone == UNSET_VALUE
179
+
180
+ # The security groups are empty by default.
181
+ @security_groups = [] if @security_groups == UNSET_VALUE
182
+
183
+ # The SSH values by default are nil, and the top-level config
184
+ # `config.ssh` values are used.
185
+ @ssh_private_key_path = nil if @ssh_private_key_path == UNSET_VALUE
186
+ @ssh_username = nil if @ssh_username == UNSET_VALUE
187
+
188
+ # Subnet is nil by default otherwise we'd launch into VPC.
189
+ @subnet_id = nil if @subnet_id == UNSET_VALUE
190
+
191
+ # Compile our region specific configurations only within
192
+ # NON-REGION-SPECIFIC configurations.
193
+ if !@__region_specific
194
+ @__region_config.each do |region, blocks|
195
+ config = self.class.new(true).merge(self)
196
+
197
+ # Execute the configuration for each block
198
+ blocks.each { |b| b.call(config) }
199
+
200
+ # The region name of the configuration always equals the
201
+ # region config name:
202
+ config.region = region
203
+
204
+ # Finalize the configuration
205
+ config.finalize!
206
+
207
+ # Store it for retrieval
208
+ @__compiled_region_configs[region] = config
209
+ end
210
+ end
211
+
212
+ # Mark that we finalized
213
+ @__finalized = true
214
+ end
215
+
216
+ def validate(machine)
217
+ errors = []
218
+
219
+ errors << I18n.t("vagrant_aws.config.region_required") if @region.nil?
220
+
221
+ if @region
222
+ # Get the configuration for the region we're using and validate only
223
+ # that region.
224
+ config = get_region_config(@region)
225
+
226
+ errors << I18n.t("vagrant_aws.config.access_key_id_required") if \
227
+ config.access_key_id.nil?
228
+ errors << I18n.t("vagrant_aws.config.secret_access_key_required") if \
229
+ config.secret_access_key.nil?
230
+ errors << I18n.t("vagrant_aws.config.ami_required") if config.ami.nil?
231
+
232
+ if config.ssh_private_key_path && \
233
+ !File.file?(File.expand_path(config.ssh_private_key_path, machine.env.root_path))
234
+ errors << I18n.t("vagrant_aws.config.private_key_missing")
235
+ end
236
+ end
237
+
238
+ { "AWS Provider" => errors }
239
+ end
240
+
241
+ # This gets the configuration for a specific region. It shouldn't
242
+ # be called by the general public and is only used internally.
243
+ def get_region_config(name)
244
+ if !@__finalized
245
+ raise "Configuration must be finalized before calling this method."
246
+ end
247
+
248
+ # Return the compiled region config
249
+ @__compiled_region_configs[name] || self
250
+ end
251
+ end
252
+ end
253
+ end
@@ -1,29 +1,19 @@
1
- module VagrantAWS
2
- module Errors
1
+ require "vagrant"
3
2
 
4
- class VagrantError < Vagrant::Errors::VagrantError
5
- def error_namespace; "vagrant.plugins.aws.errors"; end
6
- end
3
+ module VagrantPlugins
4
+ module AWS
5
+ module Errors
6
+ class VagrantAWSError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_aws.errors")
8
+ end
7
9
 
8
- class NotYetSupported < VagrantError
9
- error_key(:not_yet_supported)
10
- end
10
+ class FogError < VagrantAWSError
11
+ error_key(:fog_error)
12
+ end
11
13
 
12
- class KeyNameNotSpecified < VagrantError
13
- error_key(:key_name_not_specified)
14
- end
15
-
16
- class PrivateKeyFileNotSpecified < VagrantError
17
- error_key(:private_key_file_not_specified)
18
- end
19
-
20
- class EBSDeviceRequired < VagrantError
21
- error_key(:ebs_device_required)
22
- end
23
-
24
- class VMCreateFailure < VagrantError
25
- error_key(:vm_create_failure)
26
- end
27
-
28
- end
14
+ class RsyncError < VagrantAWSError
15
+ error_key(:rsync_error)
16
+ end
17
+ end
18
+ end
29
19
  end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant AWS 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.1.0"
10
+ raise "The Vagrant AWS plugin is only compatible with Vagrant 1.1+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module AWS
15
+ class Plugin < Vagrant.plugin("2")
16
+ name "AWS"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ machines in AWS (EC2/VPC).
20
+ DESC
21
+
22
+ config(:aws, :provider) do
23
+ require_relative "config"
24
+ Config
25
+ end
26
+
27
+ provider(:aws) do
28
+ # Setup logging and i18n
29
+ setup_logging
30
+ setup_i18n
31
+
32
+ # Return the provider
33
+ require_relative "provider"
34
+ Provider
35
+ end
36
+
37
+ # This initializes the internationalization strings.
38
+ def self.setup_i18n
39
+ I18n.load_path << File.expand_path("locales/en.yml", AWS.source_root)
40
+ I18n.reload!
41
+ end
42
+
43
+ # This sets up our log level to be whatever VAGRANT_LOG is.
44
+ def self.setup_logging
45
+ require "log4r"
46
+
47
+ level = nil
48
+ begin
49
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
50
+ rescue NameError
51
+ # This means that the logging constant wasn't found,
52
+ # which is fine. We just keep `level` as `nil`. But
53
+ # we tell the user.
54
+ level = nil
55
+ end
56
+
57
+ # Some constants, such as "true" resolve to booleans, so the
58
+ # above error checking doesn't catch it. This will check to make
59
+ # sure that the log level is an integer, as Log4r requires.
60
+ level = nil if !level.is_a?(Integer)
61
+
62
+ # Set the logging level on all "vagrant" namespaced
63
+ # logs as long as we have a valid level.
64
+ if level
65
+ logger = Log4r::Logger.new("vagrant_aws")
66
+ logger.outputters = Log4r::Outputter.stderr
67
+ logger.level = level
68
+ logger = nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,50 @@
1
+ require "log4r"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module AWS
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_aws.states.short_#{state_id}")
38
+ long = I18n.t("vagrant_aws.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
+ "AWS (#{id})"
47
+ end
48
+ end
49
+ end
50
+ end