awscli 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +15 -0
  2. data/README.rdoc +5 -0
  3. data/Rakefile +44 -0
  4. data/bin/awscli +32 -0
  5. data/features/awscli.feature +8 -0
  6. data/features/step_definitions/awscli_steps.rb +6 -0
  7. data/features/support/env.rb +15 -0
  8. data/lib/awscli.rb +44 -0
  9. data/lib/awscli/cli.rb +21 -0
  10. data/lib/awscli/cli/ec2.rb +23 -0
  11. data/lib/awscli/cli/ec2/ami.rb +46 -0
  12. data/lib/awscli/cli/ec2/ebs.rb +85 -0
  13. data/lib/awscli/cli/ec2/eip.rb +56 -0
  14. data/lib/awscli/cli/ec2/instances.rb +195 -0
  15. data/lib/awscli/cli/ec2/keypairs.rb +60 -0
  16. data/lib/awscli/cli/ec2/monitoring.rb +35 -0
  17. data/lib/awscli/cli/ec2/placement.rb +42 -0
  18. data/lib/awscli/cli/ec2/reservedinstmng.rb +45 -0
  19. data/lib/awscli/cli/ec2/secgroups.rb +66 -0
  20. data/lib/awscli/cli/ec2/spot.rb +81 -0
  21. data/lib/awscli/cli/ec2/subnet.rb +43 -0
  22. data/lib/awscli/cli/ec2/tags.rb +45 -0
  23. data/lib/awscli/cli/ec2/vmmng.rb +17 -0
  24. data/lib/awscli/cli/ec2/vpc.rb +42 -0
  25. data/lib/awscli/cli/ec2/vpc/connections.rb +0 -0
  26. data/lib/awscli/cli/ec2/vpc/cust_gateways.rb +0 -0
  27. data/lib/awscli/cli/ec2/vpc/dhcp.rb +51 -0
  28. data/lib/awscli/cli/ec2/vpc/internet_gateways.rb +58 -0
  29. data/lib/awscli/cli/ec2/vpc/net_interfaces.rb +75 -0
  30. data/lib/awscli/cli/ec2/vpc/network_acls.rb +29 -0
  31. data/lib/awscli/cli/ec2/vpc/priv_gatewats.rb +0 -0
  32. data/lib/awscli/cli/ec2/vpc/route_tables.rb +0 -0
  33. data/lib/awscli/cli/s3.rb +12 -0
  34. data/lib/awscli/cli/s3/directories.rb +82 -0
  35. data/lib/awscli/cli/s3/files.rb +77 -0
  36. data/lib/awscli/connection.rb +55 -0
  37. data/lib/awscli/ec2.rb +790 -0
  38. data/lib/awscli/errors.rb +64 -0
  39. data/lib/awscli/helper.rb +8 -0
  40. data/lib/awscli/s3.rb +108 -0
  41. data/lib/awscli/version.rb +3 -0
  42. data/test/default_test.rb +14 -0
  43. data/test/test_helper.rb +9 -0
  44. metadata +182 -0
@@ -0,0 +1,55 @@
1
+ module Awscli
2
+ class Connection
3
+ require 'awscli/errors'
4
+ require 'awscli/helper'
5
+
6
+ def initialize
7
+ #load env variable AWSCLI_CONFIG_FILE
8
+ @@aws_config_file = ENV['AWSCLI_CONFIG_FILE']
9
+ unless !@@aws_config_file.nil?
10
+ puts "Cannot find config file environment variable"
11
+ Awscli::Errors.missing_environment_variable
12
+ end
13
+ @@aws_config_file_path = File.expand_path(@@aws_config_file)
14
+ unless File.exist?(@@aws_config_file_path)
15
+ puts "Cannot locate file #{@@aws_config_file}"
16
+ Awscli::Errors.missing_config_file
17
+ end
18
+ @@config = YAML.load(File.read(@@aws_config_file_path))
19
+ unless @@config.kind_of?(Hash)
20
+ puts "Parse Error"
21
+ Awscli::Errors.missing_credentials
22
+ end
23
+ end
24
+
25
+ def request_ec2
26
+ # => returns AWS Compute connection object
27
+ @@config.merge!(:provider => 'AWS')
28
+ if @@config['region']
29
+ Awscli::Errors.invalid_region unless Awscli::Instances::REGIONS.include?(@@config['region'])
30
+ end
31
+ Fog::Compute.new(@@config)
32
+ end
33
+
34
+ def request_s3 region=nil
35
+ # => returns S3 connection object
36
+ @@config.merge!(:provider => 'AWS')
37
+ if @@config['region']
38
+ #remove region
39
+ @@config.reject!{ |k| k == "region" }
40
+ end
41
+ #parse optionally passing region
42
+ if region
43
+ Awscli::Errors.invalid_region unless Awscli::Instances::REGIONS.include?(region)
44
+ @@config.merge!(:region => region)
45
+ end
46
+ Fog::Storage.new(@@config)
47
+ end
48
+
49
+ def request_as
50
+ # => returns AWS Auto Scaling connection object
51
+ Fog::AWS::AutoScaling.new(@@config)
52
+ end
53
+
54
+ end
55
+ end
data/lib/awscli/ec2.rb ADDED
@@ -0,0 +1,790 @@
1
+ module Awscli
2
+ module EC2
3
+
4
+ class EC2
5
+
6
+ # initialize ec2 class object
7
+ # params:
8
+ # connection: Awscli::Connection.new.request_ec2
9
+ # extra options hash
10
+ def initialize connection, options = {}
11
+ @@conn = connection
12
+ end
13
+
14
+ # list instances from a specified region in a tabular format
15
+ def list_instances
16
+ @@conn.servers.table([:id, :dns_name, :flavor_id, :groups, :image_id, :key_name, :private_ip_address,
17
+ :public_ip_address, :root_device_type, :security_group_ids, :state, :tags])
18
+ end
19
+
20
+ # list available instance types
21
+ def list_flavors
22
+ @@conn.flavors.table
23
+ end
24
+
25
+ # describe instance attributes - returns information about an attribute of an instance. You can get information
26
+ # only one attribute per call.
27
+ # Avaliable attributes to request: instanceType, kernel, ramdisk, userData, disableApiTermination, instanceInitiatedShutdownBehavior,
28
+ # rootDeviceName, blockDeviceMapping, sourceDestCheck, groupSet
29
+ def describe_instance_attribute instance_id, request
30
+ valid_requests = %w(architecture ami_launch_index availability_zone block_device_mapping network_interfaces client_token
31
+ dns_name ebs_optimized groups flavor_id iam_instance_profile image_id instance_initiated_shutdown_behavior
32
+ kernel_id key_name created_at monitoring placement_group platform private_dns_name private_ip_address
33
+ public_ip_address ramdisk_id root_device_name root_device_type security_group_ids state state_reason subnet_id
34
+ tenancy tags user_data vpc_id volumes username)
35
+ #more options
36
+ #:monitor=, :username=, :private_key=, :private_key_path=, :public_key=, :public_key_path=, :username, :private_key_path, :private_key, :public_key_path, :public_key, :scp, :scp_upload, :scp_download, :ssh, :ssh_port, :sshable?
37
+ response = @@conn.servers.get(instance_id)
38
+ abort "Invalid Attribute, available attributes to request: #{valid_requests}" unless valid_requests.include?(request)
39
+ abort "InstanceId Not found :#{instance_id}, Available instnaces #{@@conn.servers.map { |x| x.id }}" unless response
40
+ puts "#{request}: #{response.send(request)}"
41
+ end
42
+
43
+ # modifies an attribute of an instance
44
+ def modify_instance_attribute instance_id, attributename, attributevalue
45
+ attrs_lookup = {
46
+ 'isize' => 'InstanceType',
47
+ 'kernel' => 'Kernel',
48
+ 'ramdisk' => 'Ramdisk',
49
+ 'userdata' => 'UserData',
50
+ 'disable_api_term' => 'DisableApiTermination',
51
+ 'inst_shutdown_beh' => 'InstanceInitiatedShutdownBehavior',
52
+ 'source_dest_check' => 'SourceDestCheck',
53
+ 'group_id' => 'GroupId'
54
+ }
55
+ valid_attributes = %w(InstanceType Kernel Ramdisk UserData DisableApiTermination InstanceInitiatedShutdownBehavior SourceDestCheck GroupId)
56
+ response = @@conn.servers.get(instance_id)
57
+ abort "InstanceId Not found :#{instance_id}, Available instnaces #{@@conn.servers.map { |x| x.id }}" unless response
58
+ abort "Instance should be in stopped state to modify its attributes" if response.state != 'stopped'
59
+ puts "#{instance_id}, #{attributename}, #{attributevalue}"
60
+ if attrs_lookup[attributename] == 'GroupId' #handle groupid which is array
61
+ puts "#{instance_id}, #{attrs_lookup[attributename]} => #{attributevalue}"
62
+ @@conn.modify_instance_attribute(instance_id, attrs_lookup[attributename] => attributevalue)
63
+ else
64
+ puts "#{instance_id}, #{attrs_lookup[attributename]}.Value => #{attributevalue}"
65
+ @@conn.modify_instance_attribute(instance_id, "#{attrs_lookup[attributename]}.Value" => attributevalue)
66
+ end
67
+ end
68
+
69
+ # reset instance attribute
70
+ def reset_instance_attribute instance_id, attribute
71
+ end
72
+
73
+ #create a single instance with options passed
74
+ def create_instance options
75
+ #validate required options
76
+ puts "Validating Options ..."
77
+ abort "Invalid Key: #{options[:key_name]}" unless @@conn.key_pairs.get(options[:key_name])
78
+ options[:groups].each do |sg|
79
+ abort "Invalid Group: #{sg}" unless @@conn.security_groups.get(sg)
80
+ end
81
+ abort "Invalid AMI: #{options[:image_id]}" unless @@conn.images.get(options[:image_id])
82
+ abort "Invalid Instance Flavor: #{options[:flavor_id]}" unless @@conn.flavors.get(options[:flavor_id])
83
+ #validate optional options
84
+ if options[:availability_zone]
85
+ available_zones = @@conn.describe_availability_zones.body['availabilityZoneInfo'].map { |az| az['zoneName'] }
86
+ abort "Invalid AvailabilityZone: #{options[:availability_zone]}" unless available_zones.include?(options[:availability_zone])
87
+ end
88
+ opts = Marshal.load(Marshal.dump(options))
89
+ wait_for_server = options[:wait_for] && opts.reject! { |k| k == 'wait_for' }
90
+ puts "Validating Options ... OK"
91
+ puts "Creating Server"
92
+ server = @@conn.servers.create(opts)
93
+ #wait for server to get created and return public_dns
94
+ if wait_for_server
95
+ print "Waiting for server to get created "
96
+ server.wait_for { print "."; ready? }
97
+ puts
98
+ puts "Server dns_name: #{server.dns_name}"
99
+ end
100
+ end
101
+
102
+ # create a new instnace(s)
103
+ def run_instances options
104
+ end
105
+
106
+ # describe instnace status
107
+ def describe_instance_status instnace_id
108
+ response = @@conn.servers.get(instance_id)
109
+ abort "InstanceId Not found :#{instance_id}" unless response
110
+ puts "Instance #{instance_id} State: #{response.state}"
111
+ end
112
+
113
+ # import instance as vm
114
+ def import_instance
115
+ end
116
+
117
+ #@@conn.server.get(instanceid).(:reboot, :save, :setup, :start, :stop)
118
+ # reboot an instance
119
+ def reboot_instance instance_id
120
+ response = @@conn.servers.get(instance_id)
121
+ abort "InstanceId Not found :#{instance_id}" unless response
122
+ response.reboot
123
+ puts "Rebooting Instance: #{instance_id}"
124
+ end
125
+
126
+ # start a stopped instance
127
+ def stop_instance instance_id
128
+ response = @@conn.servers.get(instance_id)
129
+ abort "InstanceId Not found :#{instance_id}" unless response
130
+ abort "Instance should be in running to stop it" if response.state != 'running'
131
+ response.stop
132
+ puts "Stopped Instance: #{instance_id}"
133
+ end
134
+
135
+ # stop a running isntance
136
+ def start_instance instance_id
137
+ response = @@conn.servers.get(instance_id)
138
+ abort "InstanceId Not found :#{instance_id}" unless response
139
+ abort "Instance should be stopped to start it" if response.state != 'stopped'
140
+ response.start
141
+ puts "Starting Instance: #{instance_id}"
142
+ end
143
+
144
+ # terminates an instance
145
+ def terminate_instance instance_id
146
+ response = @@conn.servers.get(instance_id)
147
+ abort "InstanceId Not found :#{instance_id}" unless response
148
+ response.destroy
149
+ puts "Terminsted Instance: #{instance_id}"
150
+ end
151
+
152
+ def get_console_output instance_id
153
+ response = @@conn.get_console_output(instance_id)
154
+ puts response
155
+ end
156
+
157
+ end # => EC2
158
+
159
+ class KeyPairs
160
+ def initialize connection, options = {}
161
+ @@conn = connection
162
+ end
163
+
164
+ def list_keypairs
165
+ @@conn.key_pairs.table
166
+ end
167
+
168
+ def create_keypair options
169
+ #validate keypair
170
+ Fog.credential = 'awscli'
171
+ abort "KeyPair '#{options[:name]}' already exists" if @@conn.key_pairs.get(options[:name])
172
+ kp = @@conn.key_pairs.create(options)
173
+ puts "Created keypair: #{options[:name]}"
174
+ p kp.write #save the key to disk
175
+ end
176
+
177
+ def delete_keypair keypair
178
+ abort "KeyPair '#{keypair}' does not exist" unless @@conn.key_pairs.get(keypair)
179
+ @@conn.key_pairs.get(keypair).destroy
180
+ puts "Deleted Keypair: #{keypair}"
181
+ end
182
+
183
+ def fingerprint keypair
184
+ response = @@conn.key_pairs.get(keypair)
185
+ abort "Cannot find key pair: #{keypair}" unless response
186
+ puts "Fingerprint for the key (#{keypair}): #{response.fingerprint}"
187
+ end
188
+
189
+ def import_keypair options
190
+ #validate if the file exists
191
+ private_key_path = if options[:private_key_path]
192
+ File.expand_path(options[:private_key_path])
193
+ else
194
+ File.expand_path("~/.ssh/#{options[:name]}")
195
+ end
196
+ public_key_path = if options[:public_key_path]
197
+ File.expand_path(options[:public_key_path])
198
+ else
199
+ File.expand_path("~/.ssh/#{options[:name]}.pub")
200
+ end
201
+ abort "Cannot find private_key_path: #{private_key_path}" unless File.exist?(private_key_path)
202
+ abort "Cannot find public_key_path: #{public_key_path}" unless File.exist?(public_key_path)
203
+ #validate if the key pair name exists
204
+ Fog.credentials = Fog.credentials.merge({ :private_key_path => private_key_path, :public_key_path => public_key_path })
205
+ @@conn.import_key_pair(options[:name], IO.read(public_key_path)) if @@conn.key_pairs.get(options[:name]).nil?
206
+ puts "Imported KeyPair with name: #{options[:name]} sucessfully, using public_key: #{public_key_path} and private_key: #{private_key_path}"
207
+ end
208
+ end # => KP
209
+
210
+ class SecGroups
211
+
212
+ #Limitations: Ec2-Classic: user can have upto 500 groups
213
+ # Ec2-VPC: user can have 50 group per VPC
214
+
215
+ def initialize connection, options = {}
216
+ @@conn = connection
217
+ end
218
+
219
+ def list_secgroups options
220
+ if options[:show_ip_permissions]
221
+ # @@conn.security_groups.table([:name, :group_id, :ip_permissions])
222
+ @@conn.security_groups.each do |sg|
223
+ id = sg.group_id
224
+ ip_permissions = sg.ip_permissions.to_yaml
225
+ Formatador.display_line("[green]#{id}[/]")
226
+ puts "#{ip_permissions}"
227
+ puts "================="
228
+ end
229
+ else
230
+ @@conn.security_groups.table([:name, :group_id, :description])
231
+ end
232
+ end
233
+
234
+ def authorize_securitygroup options
235
+ # => Ingress regular traffic -> this action applies to both EC2 and VPC Security Groups
236
+ # Each rule consists of the protocol, plus cidr range or a source group,
237
+ #for TCP/UDP protocols you must also specify the dest port or port range
238
+ #for ICMP, you must specify the icmp type and code (-1 means all types/codes)
239
+ abort "Expecting Security group id(s) of the form: 'sg-xxxxxx'" unless options[:group_id] =~ /sg-\S{8}/
240
+ abort "Invalid CIDR format" unless options[:cidr] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$/
241
+ sg = @@conn.security_groups.get_by_id(options[:group_id])
242
+ abort "Cannot find Security Group with Id: #{sg}" unless sg
243
+ begin
244
+ @@conn.authorize_security_group_ingress(
245
+ "GroupId" => options[:group_id],
246
+ "IpProtocol" => options[:protocol_type],
247
+ "FromPort" => options[:start_port],
248
+ "ToPort" => options[:end_port],
249
+ "CidrIp" => options[:cidr]
250
+ )
251
+ puts "Authorized rule"
252
+ rescue Fog::Compute::AWS::Error #=> e
253
+ abort "Error: #{$!}"
254
+ #puts $@ #backtrace
255
+ end
256
+ end
257
+
258
+ def revoke_securitygroup options
259
+ abort "Expecting Security group id(s) of the form: 'sg-xxxxxx'" unless options[:group_id] =~ /sg-\S{8}/
260
+ sg = @@conn.security_groups.get_by_id(options[:group_id])
261
+ abort "Cannot find Security Group with Id: #{sg}" unless sg
262
+ begin
263
+ response = @@conn.revoke_security_group_ingress(
264
+ "GroupId" => options[:group_id],
265
+ "IpProtocol" => options[:protocol_type],
266
+ "FromPort" => options[:start_port],
267
+ "ToPort" => options[:end_port],
268
+ "CidrIp" => options[:cidr]
269
+ )
270
+ puts "Revoked rule: #{response.body['return']}"
271
+ rescue Fog::Compute::AWS::Error #=> e
272
+ abort "Error: #{$!}"
273
+ end
274
+ end
275
+
276
+ def create_securitygroup options
277
+ abort "Error: Security Group => #{options[:name]} already exists" if @@conn.security_groups.get(options[:name])
278
+ @@conn.security_groups.create(options)
279
+ puts "Created Security Group: #{options[:name]}"
280
+ end
281
+
282
+ def delete_securitygroup options
283
+ sg = @@conn.security_groups.get_by_id(options[:group_id])
284
+ abort "Error: Cannot find Security Group with Id: #{sg}" unless sg
285
+ begin
286
+ sg.destroy
287
+ puts "Deleted Security Group with id: #{options[:group_id]}"
288
+ rescue Fog::Compute::AWS::Error #=> e
289
+ abort "Error: #{$!}"
290
+ end
291
+ end
292
+
293
+ end # => SG
294
+
295
+ class Eip
296
+ def initialize connection, options = {}
297
+ @@conn = connection
298
+ end
299
+
300
+ def list
301
+ @@conn.addresses.table
302
+ end
303
+
304
+ def create
305
+ eip = @@conn.addresses.create
306
+ puts "Created EIP: #{eip.public_ip}"
307
+ end
308
+
309
+ def delete options
310
+ abort "Invalid IP Format" unless options[:eip] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
311
+ eip = @@conn.addresses.get(options[:eip])
312
+ abort "Cannot find IP: #{options[:eip]}" unless eip
313
+ eip.destroy
314
+ puts "Deleted EIP: #{eip.public_ip}"
315
+ end
316
+
317
+ def associate options
318
+ abort "Invalid IP Format" unless options[:eip] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
319
+ eip = @@conn.addresses.get(options[:eip])
320
+ abort "Cannot find eip: #{options[:eip]}" unless eip
321
+ server = @@conn.servers.get(options[:instance_id])
322
+ abort "Cannot find server with id: #{options[:instance_id]}" unless server
323
+ begin
324
+ eip.server = server
325
+ puts "Associated EIP: #{options[:eip]} with Instance: #{options[:instance_id]}"
326
+ rescue Fog::Compute::AWS::Error
327
+ abort "Error: #{$!}"
328
+ end
329
+ end
330
+
331
+ def disassociate options
332
+ abort "Invalid IP Format" unless options[:eip] =~ /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/
333
+ abort "Cannot find EIP: #{options[:eip]}" unless @@conn.addresses.get(options[:eip])
334
+ @@conn.disassociate_address(options[:eip])
335
+ puts "Disassociated EIP: #{options[:eip]}"
336
+ end
337
+ end # => Eip
338
+
339
+ class Ami
340
+ def initialize connection, options = {}
341
+ @@conn = connection
342
+ end
343
+
344
+ def list filter
345
+ puts filter
346
+ if filter.nil?
347
+ @@conn.images.all.table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
348
+ else
349
+ @@conn.images.all(filter).table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
350
+ end
351
+ end
352
+
353
+ def show_filters
354
+ filters =
355
+ [
356
+ {:filter_name => "architecture", :desc => "Image Architecture"},
357
+ {:filter_name => "block-device-mapping.delete-on-termination", :desc => "Whether the Amazon EBS volume is deleted on instance termination"},
358
+ {:filter_name => "block-device-mapping.device-name", :desc => "Device name (e.g., /dev/sdh) for an Amazon EBS volume mapped to the image"},
359
+ {:filter_name => "block-device-mapping.snapshot-id", :desc => "Snapshot ID for an Amazon EBS volume mapped to the image"},
360
+ {:filter_name => "block-device-mapping.volume-size", :desc => "Volume size for an Amazon EBS volume mapped to the image"},
361
+ {:filter_name => "description", :desc => "Description of the AMI (provided during image creation)"},
362
+ {:filter_name => "image-id", :desc => "ID of the image" },
363
+ {:filter_name => "imgae-type", :desc => "Type of image" },
364
+ {:filter_name => "is-public", :desc => "Whether the image is public" },
365
+ {:filter_name => "kernel-id", :desc => "Kernel ID" },
366
+ {:filter_name => "manifest-location", :desc => "Location of the image manifest" },
367
+ {:filter_name => "name", :desc => "Name of the AMI (provided during image creation)" },
368
+ {:filter_name => "owner-alias", :desc => "AWS account alias (e.g., amazon or self) or AWS account ID that owns the AMI" },
369
+ {:filter_name => "owner-id", :desc => "AWS account ID of the image owner" },
370
+ {:filter_name => "platform", :desc => "Use windows if you have Windows based AMIs; otherwise leave blank" },
371
+ {:filter_name => "product-code", :desc => "Product code associated with the AMI" },
372
+ {:filter_name => "ramdisk-id", :desc => "RAM disk ID" },
373
+ {:filter_name => "root-device-name", :desc => "Root device name of the AMI (e.g., /dev/sda1)" },
374
+ {:filter_name => "root-device-type", :desc => "Root device type the AMI uses" },
375
+ {:filter_name => "state", :desc => "State of the image" },
376
+ {:filter_name => "state-reason-code", :desc => "Reason code for the state change" },
377
+ {:filter_name => "state-reason-message", :desc => "Message for the state change" },
378
+ {:filter_name => "tag-key", :desc => "Key of a tag assigned to the resource. This filter is independent of the tag-value filter" },
379
+ {:filter_name => "tag-value", :desc => "Value of a tag assigned to the resource. This filter is independent of the tag-key filter." },
380
+ {:filter_name => "virtualization-type", :desc => "Virtualization type of the image" },
381
+ {:filter_name => "hypervisor", :desc => "Hypervisor type of the image" }
382
+ ]
383
+ Formatador.display_table(filters, [:filter_name, :desc])
384
+ end
385
+
386
+ def list_amazon
387
+ @@conn.images.all('owner-alias' => 'amazon').table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
388
+ end
389
+
390
+ def create_image_from_instance options
391
+ abort "Invalid Instace: #{options[:instance_id]}" unless @@conn.servers.get(options[:instance_id])
392
+ @@conn.create_image(
393
+ options[:instance_id],
394
+ options[:name],
395
+ options[:desc],
396
+ options[:no_reboot]
397
+ )
398
+ puts "Created image from instance: #{options[:instance_id]}"
399
+ end
400
+
401
+ end # => AMI
402
+
403
+ class Ebs
404
+ def initialize connection, options = {}
405
+ @@conn = connection
406
+ end
407
+
408
+ def list options
409
+ unless options[:snapshots]
410
+ @@conn.volumes.table([:availability_zone, :delete_on_termination, :device, :id, :server_id, :size, :snapshot_id, :state, :tags, :type])
411
+ else
412
+ @@conn.snapshots.table([:id, :owner_id, :volume_id, :state, :progress, :tags, :description])
413
+ end
414
+ end
415
+
416
+ def create options
417
+ @@conn.volumes.create(options)
418
+ end
419
+
420
+ def attach_volume options
421
+ #The volume and instance must be in the same Availability Zone.
422
+ volume = @@conn.volumes.get(options[:volume_id])
423
+ volume.merge_attributes(:device => options[:device])
424
+ server = @@conn.servers.get(options[:instance_id])
425
+ abort "Cannot find volume: #{options[:volume_id]}" unless volume
426
+ abort "Cannot find instance: #{options[:instance_id]}" unless server
427
+ volume.server = server
428
+ puts "Attached volume: #{options[:volume_id]} to instance: #{options[:instance_id]}"
429
+ end
430
+
431
+ def detach_volume options
432
+ #Check if the volume is mounted and show warning regarding data loss
433
+ volume = @@conn.volumes.get(options[:volume_id])
434
+ abort "Cannot find volume: #{options[:volume_id]}" unless volume
435
+ if options[:force]
436
+ volume.force_detach
437
+ else
438
+ @@conn.detach_volume(options[:volume_id])
439
+ end
440
+ puts "Detached volume: #{options[:volume_id]}"
441
+ end
442
+
443
+ def delete_volume options
444
+ vol = @@conn.volumes.get(options[:volume_id])
445
+ abort "Cannot find volume #{options[:volume_id]}" unless vol
446
+ vol.destroy
447
+ puts "Deleted volume: #{options[:volume_id]}"
448
+ end
449
+
450
+ def create_snapshot options
451
+ abort "Cannot find volume: #{options[:volume_id]}" unless @@conn.volumes.get(options[:volume_id])
452
+ @@conn.snapshots.create(options)
453
+ puts "Created snapshot"
454
+ end
455
+
456
+ def copy_snapshot options
457
+ abort "Cannot find snapshot: #{options[:snapshot_id]}" unless @@conn.snapshots.get(options[:snapshot_id])
458
+ @@conn.copy_snapshot(options[:snapshot_id], options[:source_region])
459
+ puts "Copied snapshot"
460
+ end
461
+
462
+ def delete_snapshot options
463
+ snap = @@conn.snapshots.get(options[:snapshot_id])
464
+ abort "Cannot find snapshot: #{options[:snapshot_id]}" unless snap
465
+ snap.destroy
466
+ puts "Destroyed snapshot"
467
+ end
468
+ end # => EBS
469
+
470
+ class Monitor
471
+ def initialize connection, options = {}
472
+ @@conn = connection
473
+ end
474
+
475
+ def monitor options
476
+ options[:instance_ids].each do |instance|
477
+ abort "Invalid InstanceId: #{instance}" unless @@conn.servers.get(instance)
478
+ end
479
+ @@conn.monitor_instances(options[:instance_ids])
480
+ puts "Enabled monitoring for instnaces: #{options[:instance_ids].join(",")}"
481
+ end
482
+
483
+ def unmonitor options
484
+ options[:instance_ids].each do |instance|
485
+ abort "Invalid InstanceId: #{instance}" unless @@conn.servers.get(instance)
486
+ end
487
+ @@conn.unmonitor_instances(options[:instance_ids])
488
+ puts "Disabled monitoring for instnaces: #{options[:instance_ids].join(",")}"
489
+ end
490
+ end # => Monitor
491
+
492
+ class Tags
493
+ def initialize connection, options = {}
494
+ @@conn = connection
495
+ end
496
+
497
+ def list
498
+ @@conn.tags.table
499
+ end
500
+
501
+ def create options
502
+ @@conn.tags.create(options)
503
+ puts "Created Tag"
504
+ end
505
+
506
+ def delete options
507
+ @@conn.tags.destroy(options)
508
+ puts "Deleted Tag"
509
+ end
510
+ end # => Tags
511
+
512
+ class Placement
513
+ def initialize connection, options = {}
514
+ @@conn = connection
515
+ end
516
+
517
+ def list
518
+ @@conn.describe_placement_groups
519
+ end
520
+
521
+ def create options
522
+ @@conn.create_placement_group(options[:name], options[:strategy])
523
+ puts "Created a new placement group: #{options[:name]}"
524
+ end
525
+
526
+ def delete options
527
+ @@conn.delete_placement_group(options[:name])
528
+ puts "Deleted placement group: #{options[:name]}"
529
+ end
530
+ end # => Placement
531
+
532
+ class ReservedInstances
533
+ def initialize connection, options = {}
534
+ @@conn = connection
535
+ end
536
+
537
+ def list filters
538
+ puts filters
539
+ if filters.nil?
540
+ @@conn.describe_reserved_instances.body['reservedInstancesSet']
541
+ else
542
+ @@conn.describe_reserved_instances(filters).body['reservedInstancesSet']
543
+ end
544
+ end
545
+
546
+ def list_offerings filters
547
+ puts filters
548
+ response = if filters.nil?
549
+ @@conn.describe_reserved_instances_offerings.body['reservedInstancesOfferingsSet']
550
+ else
551
+ @@conn.describe_reserved_instances_offerings(filters).body['reservedInstancesOfferingsSet']
552
+ end
553
+ Formatador.display_table(response)
554
+ end
555
+
556
+ def list_filters
557
+ filters = [
558
+ {:filter_name => "availability-zone", :desc => "Availability Zone where the Reserved Instance can be used", :availability => "Both"},
559
+ {:filter_name => "duration", :desc => "Duration of the Reserved Instance (e.g., one year or three years), in seconds", :availability => "Both"},
560
+ {:filter_name => "fixed-price", :desc => "Purchase price of the Reserved Instance", :availability => "Both"},
561
+ {:filter_name => "instance-type", :desc => "Instance type on which the Reserved Instance can be used", :availability => "Both"},
562
+ {:filter_name => "product-description", :desc => "Reserved Instance description", :availability => "Both"},
563
+ {:filter_name => "reserved-instances-id", :desc => "Reserved Instance's ID", :availability => "Only ReservedInstances"},
564
+ {:filter_name => "reserved-instances-offering-id", :desc => "Reserved Instances offering ID", :availability => "Only reservedInstancesOfferingsSet"},
565
+ {:filter_name => "start", :desc => "Time the Reserved Instance purchase request was placed", :availability => "Only ReservedInstances"},
566
+ {:filter_name => "state", :desc => "State of the Reserved Instance", :availability => "Only ReservedInstances"},
567
+ {:filter_name => "tag-key", :desc => "Key of a tag assigned to the resource", :availability => "Only ReservedInstances"}, #This filter is independent of the tag-value filter. For example, if you use both the filter tag-key=Purpose and the filter tag-value=X, you get any resources assigned both the tag key Purpose and the tag value X
568
+ {:filter_name => "tag-value", :desc => "Value of a tag assigned to the resource", :availability => "Only ReservedInstances"}, #This filter is independent of the tag-key filter.
569
+ {:filter_name => "usage-price", :desc => "Usage price of the Reserved Instance, per hour", :availability => "Both"},
570
+ ]
571
+ Formatador.display_table(filters, [:filter_name, :desc, :availability])
572
+ end
573
+
574
+ def purchase options
575
+ @@conn.purchase_reserved_instances_offering(options[:reserved_instances_offering_id], options[:instance_count])
576
+ end
577
+ end # => ReservedInstances
578
+
579
+ class Spot
580
+ def initialize connection, options = {}
581
+ @@conn = connection
582
+ end
583
+
584
+ def describe_spot_requests
585
+ @@conn.spot_requests.table
586
+ end
587
+
588
+ def describe_spot_datafeed_subscription
589
+ @@conn.describe_spot_datafeed_subscription
590
+ end
591
+
592
+ def describe_spot_price_history filters
593
+ puts filters
594
+ response = if filters.nil?
595
+ @@conn.describe_spot_price_history.body['spotPriceHistorySet']
596
+ else
597
+ @@conn.describe_spot_price_history(filters).body['spotPriceHistorySet']
598
+ end
599
+ Formatador.display_table(response)
600
+ end
601
+
602
+ def list_filters
603
+ filters = [
604
+ {:filter_name => "instance-type", :desc => "Type of instance"},
605
+ {:filter_name => "product-description", :desc => "Product description for the Spot Price"},
606
+ {:filter_name => "spot-price", :desc => "Spot Price. The value must match exactly (or use wildcards; greater than or less than comparison is not supported)"},
607
+ {:filter_name => "timestamp", :desc => "Timestamp of the Spot Price history, e.g., 2010-08-16T05:06:11.000Z. You can use wildcards (* and ?)"},
608
+ ]
609
+ Formatador.display_table(filters, [:filter_name, :desc])
610
+ end
611
+
612
+ def create_spot_datafeed_subsription bucket, prefix
613
+ @@conn.create_spot_datafeed_subscription(bucket, prefix)
614
+ end
615
+
616
+ def delete_spot_datafeed_subsription
617
+ @@conn.delete_spot_datafeed_subscription
618
+ end
619
+
620
+ def request_spot_instances options
621
+ sr = @@conn.spot_requests.create(options)
622
+ puts "Created spot request: #{sr.id}"
623
+ end
624
+
625
+ def cancel_spot_instance_requests sid
626
+ sr = @@conn.spot_requests.get(sid)
627
+ abort "Cannot find spot request with id: #{sid}" unless sr
628
+ sr.destroy
629
+ puts "Deleted spot request: #{sid}"
630
+ end
631
+ end # => Spot
632
+
633
+ class Vpc
634
+ def initialize connection, options = {}
635
+ @@conn = connection
636
+ end
637
+
638
+ def list
639
+ @@conn.vpcs.table
640
+ end
641
+
642
+ def create options
643
+ vpc = @@conn.vpcs.create(options)
644
+ puts "Created VPC: #{vpc.id}"
645
+ end
646
+
647
+ def delete vpc_id
648
+ vpc = @@conn.vpcs.get(vpc_id)
649
+ abort "cannot find vpc: #{vpc_id}" unless vpc
650
+ vpc.destroy
651
+ puts "Deleted VPC : #{vpc_id}"
652
+ end
653
+ end # => Vpc
654
+
655
+ class Subnet
656
+ def initialize connection, options = {}
657
+ @@conn = connection
658
+ end
659
+
660
+ def list
661
+ @@conn.subnets.table
662
+ end
663
+
664
+ def create options
665
+ subnet = @@conn.subnets.create(options)
666
+ puts "Created Subnet: #{subnet.id}"
667
+ end
668
+
669
+ def delete subnet_id
670
+ subnet = @@conn.subnets.get(subnet_id)
671
+ abort "Cannot find subnet: #{subnet_id}" unless subnet
672
+ subnet.destroy
673
+ puts "Deleted subnet: #{subnet_id}"
674
+ end
675
+ end # => Subnet
676
+
677
+ class NetworkAcl
678
+ def initialize connection, options = {}
679
+ @@conn = connection
680
+ end
681
+
682
+ def list
683
+ puts "Listing Network Acls"
684
+ end
685
+
686
+ end # => NetworkAcl
687
+
688
+ class NetworkInterfaces
689
+ def initialize connection, options = {}
690
+ @@conn = connection
691
+ end
692
+
693
+ def list
694
+ @@conn.network_interfaces.table
695
+ end
696
+
697
+ def create options
698
+ nic = @@conn.network_interfaces.create(options)
699
+ puts "Create network interface #{nic.network_interface_id}"
700
+ end
701
+
702
+ def delete nic_id
703
+ nic = @@conn.network_interfaces.get(nic_id)
704
+ abort "Cannot find nic with id: #{nic_id}" unless nic
705
+ nic.destroy
706
+ puts "Deleted network interface #{nic_id}"
707
+ end
708
+
709
+ def attach nic_id, instance_id, device_index
710
+ @@conn.attach_network_interface(nic_id, instance_id, device_index)
711
+ puts "Attached Network Interface: #{nic_id} to instance: #{instance_id}"
712
+ end
713
+
714
+ def deattach attachement_id, force
715
+ @@conn.detach_network_interface attachement_id, force
716
+ puts "Deattached Network Interface with attachement_id: #{attachement_id}"
717
+ end
718
+
719
+ def modify_attribute options
720
+ case options[:attribute]
721
+ when 'description'
722
+ @@conn.modify_network_interface_attribute(options[:network_interface_id], 'description', options[:description])
723
+ when 'groupSet'
724
+ @@conn.modify_network_interface_attribute(options[:network_interface_id], 'groupSet', options[:group_set])
725
+ when 'sourceDestCheck'
726
+ @@conn.modify_network_interface_attribute(options[:network_interface_id], 'sourceDestCheck', options[:source_dest_check])
727
+ when 'attachment'
728
+ @@conn.modify_network_interface_attribute(options[:network_interface_id], 'attachment', options[:attachment])
729
+ else
730
+ abort "Invalid attribute: #{options[:attribute]}"
731
+ end
732
+ end
733
+ end # => NetworkInterfaces
734
+
735
+ class InternetGateways
736
+ def initialize connection, options = {}
737
+ @@conn = connection
738
+ end
739
+
740
+ def list
741
+ @@conn.internet_gateways.table
742
+ end
743
+
744
+ def create
745
+ gw = @@conn.internet_gateways.create
746
+ puts "Created Internet Gateway: #{gw.id}"
747
+ end
748
+
749
+ def delete gwid
750
+ gw = @@conn.internet_gateways.get(gwid)
751
+ gw.destroy
752
+ puts "Deleted Internet Gateway: #{gwid}"
753
+ end
754
+
755
+ def attach gwid, vpcid
756
+ @@conn.internet_gateways.attach(gwid, vpcid)
757
+ puts "Attached InternetGateway: #{gwid} to VPC: #{vpcid}"
758
+ end
759
+
760
+ def deattach gwid, vpcid
761
+ @@conn.internet_gateways.deattach(gwid, vpcid)
762
+ puts "Deattached InternetGateway: #{gwid} from VPC: #{vpcid}"
763
+ end
764
+ end # => InternetGateways
765
+
766
+ class Dhcp
767
+ def initialize connection, options = {}
768
+ @@conn = connection
769
+ end
770
+
771
+ def list
772
+ @@conn.dhcp_options.table
773
+ end
774
+
775
+ def create options
776
+ @@conn.dhcp_options.create(options)
777
+ end
778
+
779
+ def delete dhcp_id
780
+ dhcp = @@conn.dhcp_options(dhcp_id)
781
+ dhcp.destroy
782
+ end
783
+
784
+ def associate dhcp_ic, vpc_id
785
+ @@conn.dhcp_options.attach(dhcp_id, vpc_id)
786
+ end
787
+ end # => Dhcp
788
+
789
+ end
790
+ end