aws_helper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # aws_helper
2
+
3
+ Aws Helper for an instance
4
+
5
+ Allows functions on EBS volumes, snapshots, IP addresses and more
6
+ * initially snapshots are supported
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'aws_helper'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install aws_helper
21
+
22
+ ## Usage
23
+
24
+ Snapshot EBS attached to device /dev/sdf
25
+
26
+ export AWS_ACCESS_KEY_ID ='xxxxxxxxxxxx'
27
+ export AWS_SECRET_ACCESS_KEY ='yyyyyyyy'
28
+ export HTTP_PROXY=http://myproxy:port
29
+ aws_helper snap /dev/sdf --description zzzzzzzzz
30
+
31
+ Prune so only keep 7 snapshots:
32
+
33
+ export AWS_ACCESS_KEY_ID ='xxxxxxxxxxxx'
34
+ export AWS_SECRET_ACCESS_KEY ='yyyyyyyy'
35
+ aws_helper snap_prune /dev/sdf --snapshots_to_keep=7
36
+
37
+ NOTE: Best Practice is for your server to have an IAM role then you don't
38
+ need to specify AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
39
+
40
+ Other functions to follow
41
+
42
+
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'awshelper/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'aws_helper'
9
+ s.version = Awshelper::VERSION
10
+ s.authors = ['Neill Turner']
11
+ s.email = ['neillwturner@gmail.com']
12
+ s.homepage = 'https://github.com/neillturner/aws_helper'
13
+ s.summary = 'Aws Helper for an instance'
14
+ candidates = Dir.glob('{lib}/**/*') + ['README.md', 'aws_helper.gemspec']
15
+ candidates = candidates + Dir.glob("bin/*")
16
+ s.files = candidates.sort
17
+ s.platform = Gem::Platform::RUBY
18
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+ s.add_dependency('right_aws')
21
+ s.add_dependency('thor')
22
+ s.rubyforge_project = '[none]'
23
+ s.description = <<-EOF
24
+ == DESCRIPTION:
25
+
26
+ Aws Helper for an instance
27
+
28
+ == FEATURES:
29
+
30
+ Allows functions on EBS volumes, snapshots, IP addresses and more
31
+
32
+ EOF
33
+
34
+ end
data/bin/aws_helper ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "awshelper/cli"
4
+
5
+ Awshelper::CLI.start(ARGV)
data/lib/awshelper.rb ADDED
@@ -0,0 +1,2 @@
1
+ module Awshelper
2
+ end
@@ -0,0 +1,302 @@
1
+ require 'thor'
2
+ require 'awshelper'
3
+ require 'awshelper/ec2'
4
+ require 'syslog'
5
+
6
+ module Awshelper
7
+ class CLI < Thor
8
+ include Thor::Actions
9
+
10
+ include Awshelper::Ec2
11
+
12
+ #def ebs_create(volume_id, snapshot_id, most_recent_snapshot)
13
+ # #TO DO
14
+ # raise "Cannot create a volume with a specific id (EC2 chooses volume ids)" if volume_id
15
+ # if snapshot_id =~ /vol/
16
+ # new_resource.snapshot_id(find_snapshot_id(new_resource.snapshot_id, new_resource.most_recent_snapshot))
17
+ # end
18
+ #
19
+ # #nvid = volume_id_in_node_data
20
+ # #if nvid
21
+ # # # volume id is registered in the node data, so check that the volume in fact exists in EC2
22
+ # # vol = volume_by_id(nvid)
23
+ # # exists = vol && vol[:aws_status] != "deleting"
24
+ # # # TODO: determine whether this should be an error or just cause a new volume to be created. Currently erring on the side of failing loudly
25
+ # # raise "Volume with id #{nvid} is registered with the node but does not exist in EC2. To clear this error, remove the ['aws']['ebs_volume']['#{new_resource.name}']['volume_id'] entry from this node's data." unless exists
26
+ # #else
27
+ # # Determine if there is a volume that meets the resource's specifications and is attached to the current
28
+ # # instance in case a previous [:create, :attach] run created and attached a volume but for some reason was
29
+ # # not registered in the node data (e.g. an exception is thrown after the attach_volume request was accepted
30
+ # # by EC2, causing the node data to not be stored on the server)
31
+ # if new_resource.device && (attached_volume = currently_attached_volume(instance_id, new_resource.device))
32
+ # Chef::Log.debug("There is already a volume attached at device #{new_resource.device}")
33
+ # compatible = volume_compatible_with_resource_definition?(attached_volume)
34
+ # raise "Volume #{attached_volume[:aws_id]} attached at #{attached_volume[:aws_device]} but does not conform to this resource's specifications" unless compatible
35
+ # Chef::Log.debug("The volume matches the resource's definition, so the volume is assumed to be already created")
36
+ # converge_by("update the node data with volume id: #{attached_volume[:aws_id]}") do
37
+ # node.set['aws']['ebs_volume'][new_resource.name]['volume_id'] = attached_volume[:aws_id]
38
+ # node.save unless Chef::Config[:solo]
39
+ # end
40
+ # else
41
+ # # If not, create volume and register its id in the node data
42
+ # converge_by("create a volume with id=#{new_resource.snapshot_id} size=#{new_resource.size} availability_zone=#{new_resource.availability_zone} and update the node data with created volume's id") do
43
+ # nvid = create_volume(new_resource.snapshot_id,
44
+ # new_resource.size,
45
+ # new_resource.availability_zone,
46
+ # new_resource.timeout,
47
+ # new_resource.volume_type,
48
+ # new_resource.piops)
49
+ # node.set['aws']['ebs_volume'][new_resource.name]['volume_id'] = nvid
50
+ # node.save unless Chef::Config[:solo]
51
+ # end
52
+ # end
53
+ # #end
54
+ #end
55
+
56
+ #def ebs_attach(device, volume_id, timeout)
57
+ # # determine_volume returns a Hash, not a Mash, and the keys are
58
+ # # symbols, not strings.
59
+ # vol = determine_volume(device, volume_id)
60
+ # if vol[:aws_status] == "in-use"
61
+ # if vol[:aws_instance_id] != instance_id
62
+ # raise "Volume with id #{vol[:aws_id]} exists but is attached to instance #{vol[:aws_instance_id]}"
63
+ # else
64
+ # Chef::Log.debug("Volume is already attached")
65
+ # end
66
+ # else
67
+ # # attach the volume
68
+ # attach_volume(vol[:aws_id], instance_id, device, timeout)
69
+ # end
70
+ #end
71
+
72
+ #def ebs_detach(device, volume_id, timeout)
73
+ # vol = determine_volume(device, volume_id)
74
+ # detach_volume(vol[:aws_id], timeout)
75
+ #end
76
+
77
+ desc "snap DEVICE [VOLUME_ID]", "Take a snapshot of a EBS Disk."
78
+ option :description
79
+
80
+ long_desc <<-LONGDESC
81
+ 'snap DEVICE [VOLUME_ID] --description xxxxxx'
82
+ \x5 Take a snapshot of a EBS Disk by specifying device and/or volume_id.
83
+ \x5 All commands rely on environment variables
84
+ \x5 export AWS_ACCESS_KEY_ID ='xxxxxxxxxx'
85
+ \x5 export AWS_SECRET_ACCESS_KEY ='yyyyyy'
86
+ \x5 For example
87
+ \x5 aws_helper snap /dev/sdf
88
+ \x5 will snap shot the EBS disk attach to device /dev/xvdj
89
+ LONGDESC
90
+
91
+ def snap(device, volume_id=nil)
92
+ vol = determine_volume(device, volume_id)
93
+ snap_description = options[:description] if options[:description]
94
+ snap_description = "Created by aws_helper(#{instance_id}/#{local_ipv4}) for #{ami_id} from #{vol[:aws_id]}" if !options[:description]
95
+ snapshot = ec2.create_snapshot(vol[:aws_id],snap_description)
96
+ log("Created snapshot of #{vol[:aws_id]} as #{snapshot[:aws_id]}")
97
+ end
98
+
99
+ desc "snap_prune DEVICE [VOLUME_ID]", "Prune the number of snapshots."
100
+ option :snapshots_to_keep, :type => :numeric, :required => true
101
+
102
+ long_desc <<-LONGDESC
103
+ 'snap_prune DEVICE [VOLUME_ID] --snapshots_to_keep=<numeric>'
104
+ \x5 Prune the number of snapshots of a EBS Disk by specifying device and/or volume_id and the no to keep.
105
+ \x5 All commands rely on environment variables
106
+ \x5 export AWS_ACCESS_KEY_ID ='xxxxxxxxxxxx'
107
+ \x5 export AWS_SECRET_ACCESS_KEY ='yyyyyyyy'
108
+ \x5 For example
109
+ \x5 aws_helper snap_prune /dev/sdf --snapshots_to_keep=7
110
+ \x5 will keep the last 7 snapshots of the EBS disk attach to device /dev/xvdj
111
+ LONGDESC
112
+
113
+ def snap_prune(device, volume_id=nil)
114
+ snapshots_to_keep = options[:snapshots_to_keep]
115
+ vol = determine_volume(device, volume_id)
116
+ old_snapshots = Array.new
117
+ log("Checking for old snapshots")
118
+ ec2.describe_snapshots.sort { |a,b| b[:aws_started_at] <=> a[:aws_started_at] }.each do |snapshot|
119
+ if snapshot[:aws_volume_id] == vol[:aws_id]
120
+ log("Found old snapshot #{snapshot[:aws_id]} (#{snapshot[:aws_volume_id]}) #{snapshot[:aws_started_at]}")
121
+ old_snapshots << snapshot
122
+ end
123
+ end
124
+ if old_snapshots.length > snapshots_to_keep
125
+ old_snapshots[snapshots_to_keep, old_snapshots.length].each do |die|
126
+ log("Deleting old snapshot #{die[:aws_id]}")
127
+ ec2.delete_snapshot(die[:aws_id])
128
+ end
129
+ end
130
+ end
131
+
132
+ private
133
+
134
+ def log(message,type="info")
135
+ # $0 is the current script name
136
+ puts message
137
+ Syslog.open($0, Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.info message } if type == "info"
138
+ Syslog.open($0, Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.info message } if type == "err"
139
+ end
140
+
141
+ # Pulls the volume id from the volume_id attribute or the node data and verifies that the volume actually exists
142
+ def determine_volume(device, volume_id)
143
+ vol = currently_attached_volume(instance_id, device)
144
+ vol_id = volume_id || ( vol ? vol[:aws_id] : nil )
145
+ log("volume_id attribute not set and no volume is attached at the device #{device}",'err') unless vol_id
146
+ raise "volume_id attribute not set and no volume is attached at the device #{device}" unless vol_id
147
+
148
+ # check that volume exists
149
+ vol = volume_by_id(vol_id)
150
+ log("No volume with id #{vol_id} exists",'err') unless vol
151
+ raise "No volume with id #{vol_id} exists" unless vol
152
+
153
+ vol
154
+ end
155
+
156
+ # Retrieves information for a volume
157
+ def volume_by_id(volume_id)
158
+ ec2.describe_volumes.find{|v| v[:aws_id] == volume_id}
159
+ end
160
+
161
+ # Returns the volume that's attached to the instance at the given device or nil if none matches
162
+ def currently_attached_volume(instance_id, device)
163
+ ec2.describe_volumes.find{|v| v[:aws_instance_id] == instance_id && v[:aws_device] == device}
164
+ end
165
+
166
+ # Returns true if the given volume meets the resource's attributes
167
+ #def volume_compatible_with_resource_definition?(volume)
168
+ # if new_resource.snapshot_id =~ /vol/
169
+ # new_resource.snapshot_id(find_snapshot_id(new_resource.snapshot_id, new_resource.most_recent_snapshot))
170
+ # end
171
+ # (new_resource.size.nil? || new_resource.size == volume[:aws_size]) &&
172
+ # (new_resource.availability_zone.nil? || new_resource.availability_zone == volume[:zone]) &&
173
+ # (new_resource.snapshot_id.nil? || new_resource.snapshot_id == volume[:snapshot_id])
174
+ #end
175
+
176
+ # TODO: support tags in deswcription
177
+ #def tag_value(instance,tag_key)
178
+ # options = ec2.describe_tags({:filters => {:resource_id => instance }} )
179
+ # end
180
+
181
+ # Creates a volume according to specifications and blocks until done (or times out)
182
+ def create_volume(snapshot_id, size, availability_zone, timeout, volume_type, piops)
183
+ availability_zone ||= instance_availability_zone
184
+
185
+ # Sanity checks so we don't shoot ourselves.
186
+ raise "Invalid volume type: #{volume_type}" unless ['standard', 'io1', 'gp2'].include?(volume_type)
187
+
188
+ # PIOPs requested. Must specify an iops param and probably won't be "low".
189
+ if volume_type == 'io1'
190
+ raise 'IOPS value not specified.' unless piops >= 100
191
+ end
192
+
193
+ # Shouldn't see non-zero piops param without appropriate type.
194
+ if piops > 0
195
+ raise 'IOPS param without piops volume type.' unless volume_type == 'io1'
196
+ end
197
+
198
+ create_volume_opts = { :volume_type => volume_type }
199
+ # TODO: this may have to be casted to a string. rightaws vs aws doc discrepancy.
200
+ create_volume_opts[:iops] = piops if volume_type == 'io1'
201
+
202
+ nv = ec2.create_volume(snapshot_id, size, availability_zone, create_volume_opts)
203
+ Chef::Log.debug("Created new volume #{nv[:aws_id]}#{snapshot_id ? " based on #{snapshot_id}" : ""}")
204
+
205
+ # block until created
206
+ begin
207
+ Timeout::timeout(timeout) do
208
+ while true
209
+ vol = volume_by_id(nv[:aws_id])
210
+ if vol && vol[:aws_status] != "deleting"
211
+ if ["in-use", "available"].include?(vol[:aws_status])
212
+ Chef::Log.info("Volume #{nv[:aws_id]} is available")
213
+ break
214
+ else
215
+ Chef::Log.debug("Volume is #{vol[:aws_status]}")
216
+ end
217
+ sleep 3
218
+ else
219
+ raise "Volume #{nv[:aws_id]} no longer exists"
220
+ end
221
+ end
222
+ end
223
+ rescue Timeout::Error
224
+ raise "Timed out waiting for volume creation after #{timeout} seconds"
225
+ end
226
+
227
+ nv[:aws_id]
228
+ end
229
+
230
+ # Attaches the volume and blocks until done (or times out)
231
+ def attach_volume(volume_id, instance_id, device, timeout)
232
+ Chef::Log.debug("Attaching #{volume_id} as #{device}")
233
+ ec2.attach_volume(volume_id, instance_id, device)
234
+
235
+ # block until attached
236
+ begin
237
+ Timeout::timeout(timeout) do
238
+ while true
239
+ vol = volume_by_id(volume_id)
240
+ if vol && vol[:aws_status] != "deleting"
241
+ if vol[:aws_attachment_status] == "attached"
242
+ if vol[:aws_instance_id] == instance_id
243
+ Chef::Log.info("Volume #{volume_id} is attached to #{instance_id}")
244
+ break
245
+ else
246
+ raise "Volume is attached to instance #{vol[:aws_instance_id]} instead of #{instance_id}"
247
+ end
248
+ else
249
+ Chef::Log.debug("Volume is #{vol[:aws_status]}")
250
+ end
251
+ sleep 3
252
+ else
253
+ raise "Volume #{volume_id} no longer exists"
254
+ end
255
+ end
256
+ end
257
+ rescue Timeout::Error
258
+ raise "Timed out waiting for volume attachment after #{timeout} seconds"
259
+ end
260
+ end
261
+
262
+ # Detaches the volume and blocks until done (or times out)
263
+ def detach_volume(volume_id, timeout)
264
+ vol = volume_by_id(volume_id)
265
+ if vol[:aws_instance_id] != instance_id
266
+ Chef::Log.debug("EBS Volume #{volume_id} is not attached to this instance (attached to #{vol[:aws_instance_id]}). Skipping...")
267
+ return
268
+ end
269
+ Chef::Log.debug("Detaching #{volume_id}")
270
+ orig_instance_id = vol[:aws_instance_id]
271
+ ec2.detach_volume(volume_id)
272
+
273
+ # block until detached
274
+ begin
275
+ Timeout::timeout(timeout) do
276
+ while true
277
+ vol = volume_by_id(volume_id)
278
+ if vol && vol[:aws_status] != "deleting"
279
+ if vol[:aws_instance_id] != orig_instance_id
280
+ Chef::Log.info("Volume detached from #{orig_instance_id}")
281
+ break
282
+ else
283
+ Chef::Log.debug("Volume: #{vol.inspect}")
284
+ end
285
+ else
286
+ Chef::Log.debug("Volume #{volume_id} no longer exists")
287
+ break
288
+ end
289
+ sleep 3
290
+ end
291
+ end
292
+ rescue Timeout::Error
293
+ raise "Timed out waiting for volume detachment after #{timeout} seconds"
294
+ end
295
+ end
296
+
297
+
298
+ end
299
+
300
+ end
301
+
302
+
@@ -0,0 +1,141 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'open-uri'
19
+ require 'syslog'
20
+ require 'right_aws'
21
+
22
+
23
+ module Awshelper
24
+ module Ec2
25
+ def find_snapshot_id(volume_id="", find_most_recent=false)
26
+ snapshot_id = nil
27
+ snapshots = if find_most_recent
28
+ ec2.describe_snapshots.sort { |a,b| a[:aws_started_at] <=> b[:aws_started_at] }
29
+ else
30
+ ec2.describe_snapshots.sort { |a,b| b[:aws_started_at] <=> a[:aws_started_at] }
31
+ end
32
+ snapshots.each do |snapshot|
33
+ if snapshot[:aws_volume_id] == volume_id
34
+ snapshot_id = snapshot[:aws_id]
35
+ end
36
+ end
37
+ log("Cannot find snapshot id!",'err') unless snapshot_id
38
+ raise "Cannot find snapshot id!" unless snapshot_id
39
+ log("Snapshot ID is #{snapshot_id}")
40
+ snapshot_id
41
+ end
42
+
43
+ def ec2
44
+ @@ec2 ||= create_aws_interface
45
+ #(RightAws::Ec2)
46
+ end
47
+
48
+ def instance_id
49
+ @@instance_id ||= query_instance_id
50
+ end
51
+
52
+ def ami_id
53
+ @@ami_id ||= query_ami_id
54
+ end
55
+
56
+ def local_ipv4
57
+ @@local_ipv4 ||= query_local_ipv4
58
+ end
59
+
60
+ def instance_availability_zone
61
+ @@instance_availability_zone ||= query_instance_availability_zone
62
+ end
63
+
64
+ private
65
+
66
+ def create_aws_interface
67
+
68
+ region = instance_availability_zone
69
+ region = region[0, region.length-1]
70
+
71
+ aws_access_key = ENV['AWS_ACCESS_KEY_ID']
72
+ aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
73
+
74
+ if aws_access_key and aws_secret_access_key
75
+ RightAws::Ec2.new(aws_access_key,aws_secret_access_key, {:region => region}) # :logger => Chef::Log,
76
+ else
77
+ log("No env var AWS_ACCESS_KEY_ID and 'AWS_SECRET_ACCESS_KEY so trying role credentials")
78
+ creds = query_role_credentials
79
+ RightAws::Ec2.new(creds['AccessKeyId'], creds['SecretAccessKey'], { :region => region, :token => creds['Token']})
80
+ end
81
+ end
82
+
83
+ def query_role
84
+ r = open("http://169.254.169.254/latest/meta-data/iam/security-credentials/",options = {:proxy => proxy}).readlines.first
85
+ r
86
+ end
87
+
88
+ def query_role_credentials(role = query_role)
89
+ log("Instance has no IAM role.",'err') if role.to_s.empty?
90
+ fail "Instance has no IAM role." if role.to_s.empty?
91
+ creds = open("http://169.254.169.254/latest/meta-data/iam/security-credentials/#{role}",options = {:proxy => proxy}){|f| JSON.parse(f.string)}
92
+ log("Retrieved instance credentials for IAM role #{role}")
93
+ creds
94
+ end
95
+
96
+ def query_instance_id
97
+ instance_id = open('http://169.254.169.254/latest/meta-data/instance-id',options = {:proxy => proxy}){|f| f.gets}
98
+ log("Cannot find instance id!",'err') unless instance_id
99
+ raise "Cannot find instance id!" unless instance_id
100
+ log("Instance ID is #{instance_id}")
101
+ instance_id
102
+ end
103
+
104
+ def query_ami_id
105
+ ami_id = open('http://169.254.169.254/latest/meta-data/ami-id',options = {:proxy => proxy}){|f| f.gets}
106
+ log("Cannot find ami id!",'err') unless ami_id
107
+ raise "Cannot find instance id!" unless ami_id
108
+ log("Aim ID is #{ami_id}")
109
+ ami_id
110
+ end
111
+
112
+ def query_local_ipv4
113
+ local_ipv4 = open('http://169.254.169.254/latest/meta-data/local-ipv4',options = {:proxy => proxy}){|f| f.gets}
114
+ log("Cannot find local_ipv4!",'err') unless local_ipv4
115
+ raise "Cannot find local_ipv4!" unless local_ipv4
116
+ log("local_ipv4 is #{local_ipv4}")
117
+ local_ipv4
118
+ end
119
+
120
+ def query_instance_availability_zone
121
+ availability_zone = open('http://169.254.169.254/latest/meta-data/placement/availability-zone/', options = {:proxy => proxy}){|f| f.gets}
122
+ log("Cannot find availability zone!",'err') unless availability_zone
123
+ raise "Cannot find availability zone!" unless availability_zone
124
+ log("Instance's availability zone is #{availability_zone}")
125
+ availability_zone
126
+ end
127
+
128
+ def log(message,type="info")
129
+ # $0 is the current script name
130
+ puts message
131
+ Syslog.open($0, Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.info message } if type == "info"
132
+ Syslog.open($0, Syslog::LOG_PID | Syslog::LOG_CONS) { |s| s.info message } if type == "err"
133
+ end
134
+
135
+ def proxy
136
+ p = ENV['HTTP_PROXY'] if ENV['HTTP_PROXY']
137
+ p
138
+ end
139
+ end
140
+ end
141
+
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), 'ec2')
2
+
3
+ module AwsHelper
4
+ module Elb
5
+ include AwsHelper::Ec2
6
+
7
+ def elb
8
+ @@elb ||= create_aws_interface(RightAws::ElbInterface)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Awshelper
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Neill Turner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-11-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: right_aws
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thor
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! "== DESCRIPTION:\n\nAws Helper for an instance \n\n== FEATURES:\n\nAllows
47
+ functions on EBS volumes, snapshots, IP addresses and more \n\n"
48
+ email:
49
+ - neillwturner@gmail.com
50
+ executables:
51
+ - aws_helper
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - README.md
56
+ - aws_helper.gemspec
57
+ - bin/aws_helper
58
+ - lib/awshelper.rb
59
+ - lib/awshelper/cli.rb
60
+ - lib/awshelper/ec2.rb
61
+ - lib/awshelper/elb.rb
62
+ - lib/awshelper/version.rb
63
+ homepage: https://github.com/neillturner/aws_helper
64
+ licenses: []
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project: ! '[none]'
83
+ rubygems_version: 1.8.24
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Aws Helper for an instance
87
+ test_files: []