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
@@ -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