awsadm 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +2 -0
- data/awsadm.gemspec +27 -0
- data/bin/awsadm +9 -0
- data/lib/awsadm/cli.rb +361 -0
- data/lib/awsadm/helpers.rb +49 -0
- data/lib/awsadm/version.rb +3 -0
- data/lib/awsadm.rb +9 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e1c945a82af301d859b2e606b39443e56140faab44616d3c60eea69de9723f9d
|
4
|
+
data.tar.gz: ff6770b94e06fcd44be5bdd785c3ddcd903c130b25ddaa17acbb9d12780cb057
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 536c6fa9a349f7fbefcad3943c7aeeea2b3f784ad91617c8880cb7bed09b4f1ba88263e1753361e71194f595f836b447289d3d426413939e7c4dbc44cbe4bccc
|
7
|
+
data.tar.gz: 13501ae9f0106aab6b628aaed767ffefb8dec84d061e54b983a1758b3545199199c0b9006afa7cc9d4a5706b7f12df7efb33469fb04b01040234151d034cb37f
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016–2017 Jimmy Thelander
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# awsadm
|
2
|
+
|
3
|
+
A command-line tool to manage Amazon Web Services (AWS) Elastic Compute Cloud (EC2) spot instance requests, instances and images.
|
4
|
+
|
5
|
+
*Note: This tools is highly experimental. Use at your own risk!*
|
6
|
+
|
7
|
+
# Installation
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem install awsadm
|
11
|
+
```
|
12
|
+
|
13
|
+
# Environment variables
|
14
|
+
|
15
|
+
* AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY: [Credentials](http://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys) for using AWS
|
16
|
+
* AWS_DEFAULT_REGION: Default AWS [region](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions)
|
17
|
+
* AWSADM_SECURITY_GROUP: Name of [security group](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html) to use
|
18
|
+
|
19
|
+
# Usage
|
20
|
+
|
21
|
+
```
|
22
|
+
awsadm commands:
|
23
|
+
awsadm cancel REQUEST # Cancel spot instance REQUEST
|
24
|
+
awsadm help [COMMAND] # Describe available commands or one specific command
|
25
|
+
awsadm list OWNER # List available images by OWNER
|
26
|
+
awsadm price INSTANCE_TYPE # Show price history for INSTANCE_TYPE
|
27
|
+
awsadm save INSTANCE # Save an image from INSTANCE
|
28
|
+
awsadm start IMAGE INSTANCE_TYPE # Start INSTANCE_TYPE from IMAGE
|
29
|
+
awsadm status # Return status on spot instance requests and instances
|
30
|
+
awsadm stop INSTANCE # Stop INSTANCE
|
31
|
+
|
32
|
+
Options:
|
33
|
+
v, [--verbose], [--no-verbose]
|
34
|
+
```
|
35
|
+
|
36
|
+
# To do
|
37
|
+
|
38
|
+
* Tests, tests, tests
|
39
|
+
* More and better environment variable and input checks
|
40
|
+
* Sort image list by creation date
|
41
|
+
* Implement support for other parts of the Amazon Web Services
|
42
|
+
|
43
|
+
# License
|
44
|
+
|
45
|
+
[MIT License](http://opensource.org/licenses/MIT)
|
data/Rakefile
ADDED
data/awsadm.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'awsadm/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "awsadm"
|
8
|
+
spec.version = Awsadm::VERSION
|
9
|
+
spec.authors = ["Jimmy Thelander"]
|
10
|
+
spec.email = ["jimmy.thelander@gmail.com"]
|
11
|
+
spec.summary = %q{EXPERIMENTAL: Command-line tool for AWS resources.}
|
12
|
+
spec.description = %q{Manage your AWS resources from the command-line.}
|
13
|
+
spec.homepage = "https://github.com/thelander/awsadm"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "thor"
|
22
|
+
spec.add_dependency "aws-sdk"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
end
|
data/bin/awsadm
ADDED
data/lib/awsadm/cli.rb
ADDED
@@ -0,0 +1,361 @@
|
|
1
|
+
module Awsadm
|
2
|
+
class Cli < Thor
|
3
|
+
include Awsadm::Helpers
|
4
|
+
|
5
|
+
package_name "awsadm"
|
6
|
+
class_option :verbose, type: :boolean, aliases: :v
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super
|
10
|
+
|
11
|
+
@config = {
|
12
|
+
security_name: ENV["AWSADM_SECURITY_GROUP"] || "awsadm",
|
13
|
+
security_desc: "Allow port 22 on TCP (ssh)"
|
14
|
+
}
|
15
|
+
|
16
|
+
if ENV["AWS_ACCESS_KEY_ID"].nil? or ENV["AWS_SECRET_ACCESS_KEY"].nil?
|
17
|
+
abort "ERROR: Amazon Web Services credentials not set"
|
18
|
+
end
|
19
|
+
|
20
|
+
if ENV["AWS_DEFAULT_REGION"].nil?
|
21
|
+
abort "ERROR: Amazon Web Services default region not set"
|
22
|
+
end
|
23
|
+
|
24
|
+
Aws.config.update({
|
25
|
+
credentials: Aws::Credentials.new(
|
26
|
+
ENV["AWS_ACCESS_KEY_ID"],
|
27
|
+
ENV["AWS_SECRET_ACCESS_KEY"]
|
28
|
+
),
|
29
|
+
region: ENV["AWS_DEFAULT_REGION"]
|
30
|
+
})
|
31
|
+
|
32
|
+
@client = Aws::EC2::Client.new
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "list OWNER", "List available images by OWNER"
|
36
|
+
def list owner=""
|
37
|
+
print "Finding images... " if options[:verbose]
|
38
|
+
|
39
|
+
if owner.empty?
|
40
|
+
images = @client.describe_images[0]
|
41
|
+
else
|
42
|
+
images = @client.describe_images({
|
43
|
+
owners: [owner]
|
44
|
+
})[0]
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "#{images.count} image(s) found." if options[:verbose]
|
48
|
+
|
49
|
+
image_table_header = ["IMAGE", "NAME", "PLATFORM", "STATE", "CREATED"]
|
50
|
+
image_table_items = []
|
51
|
+
|
52
|
+
images.each do |image|
|
53
|
+
image_table_items << [
|
54
|
+
image.image_id,
|
55
|
+
image.name.nil? ? "-" : truncate(image.name),
|
56
|
+
image.platform,
|
57
|
+
image.state,
|
58
|
+
empty?(image.creation_date) ? "-" : time_string_format(image.creation_date)
|
59
|
+
]
|
60
|
+
end
|
61
|
+
|
62
|
+
if image_table_items.size > 0
|
63
|
+
puts_table image_table_header, image_table_items
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "start IMAGE INSTANCE_TYPE", "Start INSTANCE_TYPE from IMAGE"
|
68
|
+
def start image_id, instance_type
|
69
|
+
print "Finding image... " if options[:verbose]
|
70
|
+
|
71
|
+
begin
|
72
|
+
image = @client.describe_images({
|
73
|
+
image_ids: [image_id]
|
74
|
+
})[0][0]
|
75
|
+
rescue Aws::EC2::Errors::InvalidAMIIDMalformed
|
76
|
+
abort "ERROR: Invalid image ID"
|
77
|
+
rescue Aws::EC2::Errors::InvalidAMIIDNotFound
|
78
|
+
abort "ERROR: Image not found"
|
79
|
+
end
|
80
|
+
|
81
|
+
puts "Found." if options[:verbose]
|
82
|
+
|
83
|
+
image_table_header = ["IMAGE", "NAME", "PLATFORM", "STATE", "CREATED"]
|
84
|
+
image_table_items = []
|
85
|
+
|
86
|
+
image_table_items = [[
|
87
|
+
image.image_id,
|
88
|
+
image.name.nil? ? "-" : truncate(image.name),
|
89
|
+
image.platform,
|
90
|
+
image.state,
|
91
|
+
empty?(image.creation_date) ? "-" : time_string_format(image.creation_date)
|
92
|
+
]]
|
93
|
+
|
94
|
+
if image_table_items.size > 0
|
95
|
+
puts_table image_table_header, image_table_items
|
96
|
+
end
|
97
|
+
|
98
|
+
puts
|
99
|
+
print "Finding security group \"#{@config[:security_name]}\"... " if options[:verbose]
|
100
|
+
|
101
|
+
begin
|
102
|
+
security_group = @client.describe_security_groups({
|
103
|
+
group_names: [@config[:security_name]]
|
104
|
+
})[0][0]
|
105
|
+
rescue Aws::EC2::Errors::InvalidGroupNotFound
|
106
|
+
puts "Not found." if options[:verbose]
|
107
|
+
print "Creating one with defaults... " if options[:verbose]
|
108
|
+
|
109
|
+
@client.create_security_group({
|
110
|
+
group_name: @config[:security_name],
|
111
|
+
description: @config[:security_desc]
|
112
|
+
})
|
113
|
+
|
114
|
+
default_security.each do |rule|
|
115
|
+
@client.authorize_security_group_ingress(rule.merge({
|
116
|
+
group_name: @config[:security_name]
|
117
|
+
}))
|
118
|
+
end
|
119
|
+
|
120
|
+
security_group = @client.describe_security_groups({
|
121
|
+
group_names: [@config[:security_name]]
|
122
|
+
})[0][0]
|
123
|
+
end
|
124
|
+
|
125
|
+
puts "Done." if options[:verbose]
|
126
|
+
|
127
|
+
rule_table_header = ["PROTOCOL", "PORT RANGE", "IP RANGES"]
|
128
|
+
rule_table_items = []
|
129
|
+
|
130
|
+
security_group.ip_permissions.each do |p|
|
131
|
+
ip_ranges = []
|
132
|
+
p.ip_ranges.each do |ip|
|
133
|
+
ip_ranges << ip.cidr_ip
|
134
|
+
end
|
135
|
+
|
136
|
+
rule_table_items << [
|
137
|
+
p.ip_protocol,
|
138
|
+
"#{p.from_port} to #{p.to_port}",
|
139
|
+
"#{ip_ranges.join(", ")}"
|
140
|
+
]
|
141
|
+
end
|
142
|
+
|
143
|
+
puts_table rule_table_header, rule_table_items, false
|
144
|
+
puts
|
145
|
+
print "Retrieving price history... " if options[:verbose]
|
146
|
+
|
147
|
+
if image.platform.nil? or image.platform.empty?
|
148
|
+
price_history = @client.describe_spot_price_history({
|
149
|
+
instance_types: [instance_type],
|
150
|
+
start_time: Time.now
|
151
|
+
})[0]
|
152
|
+
else
|
153
|
+
price_history = @client.describe_spot_price_history({
|
154
|
+
instance_types: [instance_type],
|
155
|
+
start_time: Time.now,
|
156
|
+
product_descriptions: [image.platform.capitalize]
|
157
|
+
})[0]
|
158
|
+
end
|
159
|
+
|
160
|
+
puts "Retrieved." if options[:verbose]
|
161
|
+
|
162
|
+
price_table_header = ["ZONE", "INSTANCE TYPE", "PLATFORM", "PRICE"]
|
163
|
+
price_table_items = []
|
164
|
+
prices = []
|
165
|
+
|
166
|
+
price_history.each do |p|
|
167
|
+
price = p.spot_price.to_f.round(3)
|
168
|
+
prices << price
|
169
|
+
price_table_items << [
|
170
|
+
p.availability_zone,
|
171
|
+
instance_type,
|
172
|
+
p.product_description.downcase,
|
173
|
+
price
|
174
|
+
]
|
175
|
+
end
|
176
|
+
|
177
|
+
puts_table price_table_header, price_table_items
|
178
|
+
puts
|
179
|
+
|
180
|
+
suggested_bid = bid_formula prices
|
181
|
+
bid = ask "How much are you willing to bid for the instance (#{suggested_bid} usd/hour)?"
|
182
|
+
bid = suggested_bid if bid.nil? or bid.empty?
|
183
|
+
exit unless valid_float? bid
|
184
|
+
bid.to_f.round(3)
|
185
|
+
|
186
|
+
print "Creating instance request... " if options[:verbose]
|
187
|
+
|
188
|
+
request = @client.request_spot_instances({
|
189
|
+
spot_price: bid.to_s,
|
190
|
+
launch_specification: {
|
191
|
+
image_id: image_id,
|
192
|
+
security_groups: [@config[:security_name]],
|
193
|
+
instance_type: instance_type
|
194
|
+
}
|
195
|
+
})
|
196
|
+
|
197
|
+
puts "Created." if options[:verbose]
|
198
|
+
puts "Run \"awsadm status\" to see status." if options[:verbose]
|
199
|
+
end
|
200
|
+
|
201
|
+
desc "status", "Return status on spot instance requests and instances"
|
202
|
+
def status
|
203
|
+
requests = @client.describe_spot_instance_requests()[0]
|
204
|
+
|
205
|
+
request_table_header = ["REQUEST", "INSTANCE", "STATE", "PRICE", "AGE"]
|
206
|
+
request_table_items = []
|
207
|
+
|
208
|
+
requests.each do |r|
|
209
|
+
request_table_items << [
|
210
|
+
r.spot_instance_request_id,
|
211
|
+
r.instance_id.nil? ? "-" : r.instance_id,
|
212
|
+
r.status.code,
|
213
|
+
r.spot_price.to_f.round(3).to_s,
|
214
|
+
r.create_time.nil? ? "-" : "#{minutes_since(r.create_time)}m"
|
215
|
+
]
|
216
|
+
end
|
217
|
+
|
218
|
+
if request_table_items.size > 0
|
219
|
+
puts_table request_table_header, request_table_items
|
220
|
+
end
|
221
|
+
|
222
|
+
instances = @client.describe_instances()[0]
|
223
|
+
|
224
|
+
instance_table_header = [
|
225
|
+
"INSTANCE", "IMAGE", "STATE", "IP", "ZONE", "AGE"
|
226
|
+
]
|
227
|
+
instance_table_items = []
|
228
|
+
|
229
|
+
instances.each do |i|
|
230
|
+
i = i.instances.first
|
231
|
+
ni = i.network_interfaces.first
|
232
|
+
|
233
|
+
instance_table_items << [
|
234
|
+
i.instance_id,
|
235
|
+
i.image_id,
|
236
|
+
i.state.name,
|
237
|
+
i.state.name == "running" ? ni.association.public_ip : "-",
|
238
|
+
i.placement.availability_zone,
|
239
|
+
i.state.name == "running" ? "#{minutes_since(i.launch_time)}m" : "-"
|
240
|
+
]
|
241
|
+
end
|
242
|
+
|
243
|
+
if instance_table_items.size > 0
|
244
|
+
puts
|
245
|
+
puts_table instance_table_header, instance_table_items
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
desc "stop INSTANCE", "Stop INSTANCE"
|
250
|
+
def stop instance_id
|
251
|
+
if instance_id == "all"
|
252
|
+
instances = @client.describe_instances()[0]
|
253
|
+
else
|
254
|
+
begin
|
255
|
+
instances = @client.describe_instances({
|
256
|
+
instance_ids: [instance_id]
|
257
|
+
})[0]
|
258
|
+
rescue Aws::EC2::Errors::InvalidInstanceIDMalformed
|
259
|
+
abort "ERROR: Invalid instance ID"
|
260
|
+
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound
|
261
|
+
abort "ERROR: Instance not found"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
instance_ids = []
|
266
|
+
instances.each do |i|
|
267
|
+
i = i.instances.first
|
268
|
+
instance_ids << i.instance_id
|
269
|
+
end
|
270
|
+
|
271
|
+
@client.terminate_instances({
|
272
|
+
instance_ids: instance_ids
|
273
|
+
})
|
274
|
+
|
275
|
+
print "Instance(s) have been stopped. " if options[:verbose]
|
276
|
+
puts "Run \"awsadm status\" to see status." if options[:verbose]
|
277
|
+
end
|
278
|
+
|
279
|
+
desc "cancel REQUEST", "Cancel spot instance REQUEST"
|
280
|
+
def cancel request_id
|
281
|
+
if request_id == "all"
|
282
|
+
requests = @client.describe_spot_instance_requests()[0]
|
283
|
+
else
|
284
|
+
begin
|
285
|
+
requests = @client.describe_spot_instance_requests({
|
286
|
+
spot_instance_request_ids: [request_id]
|
287
|
+
})[0]
|
288
|
+
rescue Aws::EC2::Errors::InvalidSpotInstanceRequestIDMalformed
|
289
|
+
abort "ERROR: Invalid request ID"
|
290
|
+
rescue Aws::EC2::Errors::InvalidSpotInstanceRequestIDNotFound
|
291
|
+
abort "ERROR: Request not found"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
request_ids = []
|
296
|
+
|
297
|
+
requests.each do |r|
|
298
|
+
request_ids << r.spot_instance_request_id
|
299
|
+
end
|
300
|
+
|
301
|
+
if request_ids.size > 0
|
302
|
+
@client.cancel_spot_instance_requests({
|
303
|
+
spot_instance_request_ids: request_ids
|
304
|
+
})
|
305
|
+
end
|
306
|
+
|
307
|
+
print "Instance request(s) cancelled. " if options[:verbose]
|
308
|
+
puts "Run \"awsadm status\" to see status." if options[:verbose]
|
309
|
+
end
|
310
|
+
|
311
|
+
desc "save INSTANCE", "Save an image from INSTANCE"
|
312
|
+
def save instance_id
|
313
|
+
begin
|
314
|
+
instance = @client.describe_instances({
|
315
|
+
instance_ids: [instance_id]
|
316
|
+
})[0][0]
|
317
|
+
rescue Aws::EC2::Errors::InvalidInstanceIDMalformed
|
318
|
+
abort "ERROR: Invalid instance ID"
|
319
|
+
rescue Aws::EC2::Errors::InvalidInstanceIDNotFound
|
320
|
+
abort "ERROR: Instance not found"
|
321
|
+
end
|
322
|
+
|
323
|
+
image = @client.create_image({
|
324
|
+
instance_id: instance_id,
|
325
|
+
name: "awsadm-#{instance_id}-#{Time.now.strftime('%Y%m%d-%H%M%S%L')}"
|
326
|
+
})
|
327
|
+
|
328
|
+
print "Instance saved. " if options[:verbose]
|
329
|
+
puts "Run \"awsadm list\" to see images." if options[:verbose]
|
330
|
+
end
|
331
|
+
|
332
|
+
desc "price INSTANCE_TYPE", "Show price history for INSTANCE_TYPE"
|
333
|
+
def price instance_type
|
334
|
+
print "Retrieving price history... " if options[:verbose]
|
335
|
+
|
336
|
+
price_history = @client.describe_spot_price_history({
|
337
|
+
instance_types: [instance_type],
|
338
|
+
start_time: Time.now
|
339
|
+
})[0]
|
340
|
+
|
341
|
+
puts "Retrieved." if options[:verbose]
|
342
|
+
|
343
|
+
price_table_header = ["ZONE", "INSTANCE TYPE", "PLATFORM", "PRICE"]
|
344
|
+
price_table_items = []
|
345
|
+
prices = []
|
346
|
+
|
347
|
+
price_history.each do |p|
|
348
|
+
price = p.spot_price.to_f.round(3)
|
349
|
+
prices << price
|
350
|
+
price_table_items << [
|
351
|
+
p.availability_zone,
|
352
|
+
p.instance_type,
|
353
|
+
p.product_description.downcase,
|
354
|
+
price
|
355
|
+
]
|
356
|
+
end
|
357
|
+
|
358
|
+
puts_table price_table_header, price_table_items
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Awsadm::Helpers
|
2
|
+
def bid_formula x
|
3
|
+
y = 0.02
|
4
|
+
(x.max + y).round(3)
|
5
|
+
end
|
6
|
+
|
7
|
+
def minutes_since time
|
8
|
+
(time - Time.now).to_i.abs / 60
|
9
|
+
end
|
10
|
+
|
11
|
+
def time_format time
|
12
|
+
time.strftime("%Y-%m-%d")
|
13
|
+
end
|
14
|
+
|
15
|
+
def time_string_format time
|
16
|
+
time_format(Time.parse(time))
|
17
|
+
end
|
18
|
+
|
19
|
+
def truncate string, max=24
|
20
|
+
string.length > max ? "#{string[0..max]}..." : string
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_float? string
|
24
|
+
!!Float(string) rescue false
|
25
|
+
end
|
26
|
+
|
27
|
+
def puts_table header, items, sort=true
|
28
|
+
full_table = []
|
29
|
+
full_table = items
|
30
|
+
full_table.sort! if sort
|
31
|
+
full_table.unshift header
|
32
|
+
print_table full_table, colwidth: 14
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty? string
|
36
|
+
(string.nil? or string.empty?)
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_security
|
40
|
+
[
|
41
|
+
{
|
42
|
+
ip_protocol: "tcp",
|
43
|
+
cidr_ip: "0.0.0.0/0",
|
44
|
+
from_port: 22,
|
45
|
+
to_port: 22
|
46
|
+
}
|
47
|
+
]
|
48
|
+
end
|
49
|
+
end
|
data/lib/awsadm.rb
ADDED
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: awsadm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jimmy Thelander
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.11'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Manage your AWS resources from the command-line.
|
84
|
+
email:
|
85
|
+
- jimmy.thelander@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- awsadm.gemspec
|
96
|
+
- bin/awsadm
|
97
|
+
- lib/awsadm.rb
|
98
|
+
- lib/awsadm/cli.rb
|
99
|
+
- lib/awsadm/helpers.rb
|
100
|
+
- lib/awsadm/version.rb
|
101
|
+
homepage: https://github.com/thelander/awsadm
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.7.3
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: 'EXPERIMENTAL: Command-line tool for AWS resources.'
|
125
|
+
test_files: []
|