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 +42 -0
- data/aws_helper.gemspec +34 -0
- data/bin/aws_helper +5 -0
- data/lib/awshelper.rb +2 -0
- data/lib/awshelper/cli.rb +302 -0
- data/lib/awshelper/ec2.rb +141 -0
- data/lib/awshelper/elb.rb +12 -0
- data/lib/awshelper/version.rb +3 -0
- metadata +87 -0
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
|
+
|
data/aws_helper.gemspec
ADDED
@@ -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
data/lib/awshelper.rb
ADDED
@@ -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
|
+
|
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: []
|