lsaws 0.2.0 → 0.3.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 +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +7 -10
- data/lib/lsaws/lister.rb +61 -21
- data/lib/lsaws/sdk_parser.rb +30 -4
- data/lib/lsaws/version.rb +1 -1
- data/lib/lsaws.rb +6 -0
- data/lsaws.yml +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc348c9f2fd3c7a4f3159329804809b7800307aa42eedfdc01b17d9c8e220021
|
4
|
+
data.tar.gz: b558293f705f7df368d75aeb41a6bc133fd7bb3a366ddef2f790f99267c019c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c2a9d0c17689697c13aa3be30e05b6406a7d0031102342e3bddfcd56a486b73e23c57cdfcae8fa9653443e66fefb8b5d962c57abd044f103ecf26e85a69d7a4
|
7
|
+
data.tar.gz: 2dc1db342c3d646d9b5e7504b01cf2fdd9f83ad9e90298bde50f69eaf9b5adffce0405a0b8b86ea7890617fb484262780397a9ee08bb0e43a9a652d22d8672e8
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
lsaws (0.
|
4
|
+
lsaws (0.3.0)
|
5
5
|
aws-sdk-core (~> 3.131)
|
6
6
|
tabulo (~> 2.8)
|
7
7
|
|
@@ -1379,27 +1379,24 @@ GEM
|
|
1379
1379
|
aws-sigv2 (1.1.0)
|
1380
1380
|
aws-sigv4 (1.5.2)
|
1381
1381
|
aws-eventstream (~> 1, >= 1.0.2)
|
1382
|
+
coderay (1.1.3)
|
1382
1383
|
concurrent-ruby (1.2.0)
|
1383
|
-
debug (1.7.1)
|
1384
|
-
irb (>= 1.5.0)
|
1385
|
-
reline (>= 0.3.1)
|
1386
1384
|
diff-lcs (1.5.0)
|
1387
1385
|
i18n (1.12.0)
|
1388
1386
|
concurrent-ruby (~> 1.0)
|
1389
|
-
io-console (0.6.0)
|
1390
|
-
irb (1.6.2)
|
1391
|
-
reline (>= 0.3.0)
|
1392
1387
|
jmespath (1.6.2)
|
1393
1388
|
json (2.6.3)
|
1389
|
+
method_source (1.0.0)
|
1394
1390
|
minitest (5.17.0)
|
1395
1391
|
parallel (1.22.1)
|
1396
1392
|
parser (3.2.0.0)
|
1397
1393
|
ast (~> 2.4.1)
|
1394
|
+
pry (0.14.2)
|
1395
|
+
coderay (~> 1.1)
|
1396
|
+
method_source (~> 1.0)
|
1398
1397
|
rainbow (3.1.1)
|
1399
1398
|
rake (13.0.6)
|
1400
1399
|
regexp_parser (2.6.2)
|
1401
|
-
reline (0.3.2)
|
1402
|
-
io-console (~> 0.5)
|
1403
1400
|
rexml (3.2.5)
|
1404
1401
|
rspec (3.12.0)
|
1405
1402
|
rspec-core (~> 3.12.0)
|
@@ -1441,8 +1438,8 @@ PLATFORMS
|
|
1441
1438
|
DEPENDENCIES
|
1442
1439
|
activesupport (~> 7.0)
|
1443
1440
|
aws-sdk
|
1444
|
-
debug
|
1445
1441
|
lsaws!
|
1442
|
+
pry
|
1446
1443
|
rake (~> 13.0)
|
1447
1444
|
rspec (~> 3.0)
|
1448
1445
|
rubocop (~> 1.21)
|
data/lib/lsaws/lister.rb
CHANGED
@@ -3,20 +3,20 @@
|
|
3
3
|
require "aws-sdk-core"
|
4
4
|
require "json"
|
5
5
|
require "tabulo"
|
6
|
-
require "yaml"
|
7
6
|
|
8
7
|
module Lsaws
|
9
8
|
class Lister
|
10
|
-
CONFIG = YAML.load_file(File.join(Lsaws.root, "lsaws.yml"))
|
11
|
-
|
12
9
|
include Utils
|
13
10
|
|
11
|
+
NEXT_PAGE_FIELDS = %i[next_token next_marker next_page_token page_token].freeze
|
12
|
+
|
14
13
|
def initialize(options)
|
15
14
|
@options = options
|
15
|
+
@options[:max_width] = nil if @options[:max_width].to_i.zero?
|
16
16
|
end
|
17
17
|
|
18
18
|
def _prepare_entities(sdk, type, &block)
|
19
|
-
edef =
|
19
|
+
edef = Lsaws.config.dig(sdk, type)
|
20
20
|
return _prepare_entities(sdk, edef, &block) if edef.is_a?(String) # redirect like 'default' -> 'instances'
|
21
21
|
|
22
22
|
edef ||= {}
|
@@ -33,7 +33,7 @@ module Lsaws
|
|
33
33
|
sdkp = SDKParser.new(sdk)
|
34
34
|
client_class = edef["client_class"] || sdkp.client_class_name
|
35
35
|
client = Kernel.const_get(client_class).new
|
36
|
-
method_name = edef["method"] ||
|
36
|
+
method_name = edef["method"] || sdkp.etype2method(type)
|
37
37
|
unless client.respond_to?(method_name)
|
38
38
|
if type == "default"
|
39
39
|
warn "[!] no default entity type set for #{sdk.inspect} SDK"
|
@@ -44,27 +44,41 @@ module Lsaws
|
|
44
44
|
list_entity_types(sdk)
|
45
45
|
exit 1
|
46
46
|
end
|
47
|
+
warn "[d] #{method_name} #{params}" if @options[:debug]
|
47
48
|
results = client.send(method_name, params)
|
48
49
|
|
49
|
-
|
50
|
+
warn "[d] #{File.basename(__FILE__)}:#{__LINE__} results:\n#{results.pretty_inspect}" if @options[:debug]
|
50
51
|
|
51
52
|
if !edef["result_keys"] && results.any?
|
52
53
|
r = results.first
|
53
54
|
r = r.last if r.is_a?(Array)
|
54
|
-
edef["result_keys"] =
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
edef["result_keys"] =
|
56
|
+
if r.respond_to?(type)
|
57
|
+
[type]
|
58
|
+
elsif NEXT_PAGE_FIELDS.any? { |t| r.respond_to?(t) }
|
59
|
+
data_members = r.members - NEXT_PAGE_FIELDS
|
60
|
+
if data_members.size == 1
|
61
|
+
[data_members[0]]
|
62
|
+
else
|
63
|
+
# XXX what if there's more than one array?
|
64
|
+
[data_members.find { |key| r[key].is_a?(Array) }].compact
|
65
|
+
end
|
66
|
+
else
|
67
|
+
[]
|
68
|
+
end
|
59
69
|
end
|
70
|
+
|
60
71
|
edef["result_keys"].each do |key|
|
61
72
|
results = if results.is_a?(Array)
|
62
|
-
results.map(&key.to_sym).flatten
|
73
|
+
results.map(&key.to_sym).flatten # TODO: is flatten necessary?
|
63
74
|
else
|
64
|
-
results
|
75
|
+
results[key]
|
65
76
|
end
|
66
77
|
end
|
78
|
+
|
79
|
+
warn "[d] #{File.basename(__FILE__)}:#{__LINE__} results:\n#{results.pretty_inspect}" if @options[:debug]
|
67
80
|
edef["cols"] = @options[:show_cols] if @options[:show_cols].any?
|
81
|
+
warn "[d] edef: #{edef}" if @options[:debug]
|
68
82
|
|
69
83
|
col_defs = {}
|
70
84
|
Array(edef["cols"]).each do |r|
|
@@ -77,10 +91,12 @@ module Lsaws
|
|
77
91
|
raise Error, "unexpected #{r.inspect}"
|
78
92
|
end
|
79
93
|
end
|
94
|
+
# TODO: check with all types
|
80
95
|
col_defs["tags"] = _convert_tags_proc if @options[:show_tags] || col_defs["tags"]
|
81
96
|
|
82
97
|
results ||= []
|
83
|
-
|
98
|
+
warn "[d] #{results.inspect}" if @options[:debug]
|
99
|
+
if results.respond_to?(:any?) && results.any? && !results.first.respond_to?(:name) && results.first.respond_to?(:tags)
|
84
100
|
results.first.class.class_eval do
|
85
101
|
def name
|
86
102
|
tags.find { |tag| tag.key == "Name" }&.value
|
@@ -88,9 +104,19 @@ module Lsaws
|
|
88
104
|
end
|
89
105
|
end
|
90
106
|
|
91
|
-
|
92
|
-
|
93
|
-
|
107
|
+
case results
|
108
|
+
when Hash
|
109
|
+
col_defs = {
|
110
|
+
key: :first,
|
111
|
+
value: :last
|
112
|
+
}
|
113
|
+
when Array
|
114
|
+
# ok
|
115
|
+
else
|
116
|
+
# ec2 instance_event_notification_attributes
|
117
|
+
# 'Array(results)' doesn't work here
|
118
|
+
results = [results]
|
119
|
+
end
|
94
120
|
|
95
121
|
if block_given?
|
96
122
|
results.map do |entity|
|
@@ -106,6 +132,9 @@ module Lsaws
|
|
106
132
|
if rows.is_a?(Array) && rows[0].is_a?(String)
|
107
133
|
# sqs
|
108
134
|
cols = { value: proc { |entity| entity } }
|
135
|
+
elsif rows.is_a?(Array) && rows[0].is_a?(Hash)
|
136
|
+
# securitylake:log_sources
|
137
|
+
cols = { value: proc { |entity| entity } }
|
109
138
|
elsif rows.respond_to?(:members)
|
110
139
|
rows = [rows]
|
111
140
|
end
|
@@ -168,12 +197,23 @@ module Lsaws
|
|
168
197
|
_list_array SDKParser.new(sdk).entity_types
|
169
198
|
end
|
170
199
|
|
200
|
+
# elasticache:global_replication_groups has 'members' as a column, so cannot just use `rows.members`
|
201
|
+
# assuming row is always subclass of Struct here
|
202
|
+
def _get_cols(row)
|
203
|
+
if row.is_a?(Struct)
|
204
|
+
Struct.instance_method(:members).bind_call(row)
|
205
|
+
else
|
206
|
+
row.members
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
171
210
|
def _tabulo_guess_max_cols(rows, _cols)
|
172
|
-
|
211
|
+
all_cols = _get_cols(rows[0])
|
212
|
+
max_cols = all_cols.size
|
173
213
|
return max_cols if max_cols < 4 || !@options[:max_width]
|
174
214
|
|
175
215
|
4.upto(max_cols) do |ncols|
|
176
|
-
tbl = Tabulo::Table.new(rows[0, 100], *
|
216
|
+
tbl = Tabulo::Table.new(rows[0, 100], *all_cols[0, ncols])
|
177
217
|
tbl.autosize_columns
|
178
218
|
tbl_width = tbl.column_registry.values.map { |c| c.padded_width + 1 }.inject(:+) + 1
|
179
219
|
return ncols - 1 if tbl_width >= @options[:max_width]
|
@@ -187,7 +227,7 @@ module Lsaws
|
|
187
227
|
elsif type == :list
|
188
228
|
return list_entity_types(sdk)
|
189
229
|
elsif type == :all
|
190
|
-
|
230
|
+
SDKParser.new(sdk).entity_types.each do |etype|
|
191
231
|
puts "#{etype}:"
|
192
232
|
process_command(sdk, etype)
|
193
233
|
end
|
@@ -208,7 +248,7 @@ module Lsaws
|
|
208
248
|
cols.each { |name, func| tbl.add_column(name, &func) }
|
209
249
|
else
|
210
250
|
max_cols = _tabulo_guess_max_cols(rows, cols)
|
211
|
-
rows[0]
|
251
|
+
_get_cols(rows[0])[0, max_cols].each { |col| tbl.add_column(col) }
|
212
252
|
end
|
213
253
|
puts tbl.pack(max_table_width: @options[:max_width])
|
214
254
|
when :json
|
data/lib/lsaws/sdk_parser.rb
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
module Lsaws
|
4
4
|
class SDKParser
|
5
|
+
IGNORED_SDKS = [
|
6
|
+
"core", "resources", # do not contain any resource listing methods
|
7
|
+
"s3control" # requires account_id param for all requests
|
8
|
+
].freeze
|
9
|
+
|
5
10
|
def self.get_sdks
|
6
11
|
r = []
|
7
12
|
Gem.path.each do |p|
|
@@ -12,7 +17,7 @@ module Lsaws
|
|
12
17
|
a.size == 4 ? a[2] : nil
|
13
18
|
end)
|
14
19
|
end
|
15
|
-
r.compact.uniq.sort -
|
20
|
+
r.compact.uniq.sort - IGNORED_SDKS
|
16
21
|
end
|
17
22
|
|
18
23
|
def initialize(sdk)
|
@@ -23,6 +28,7 @@ module Lsaws
|
|
23
28
|
def client_class_name
|
24
29
|
@client_class_name ||=
|
25
30
|
begin
|
31
|
+
# TODO: use constants from gems/aws-sdk-resources-x.xxx
|
26
32
|
c = Aws.constants.find { |x| x.to_s.downcase == @sdk }
|
27
33
|
"Aws::#{c}::Client"
|
28
34
|
end
|
@@ -32,10 +38,25 @@ module Lsaws
|
|
32
38
|
@client_class ||= Kernel.const_get(client_class_name)
|
33
39
|
end
|
34
40
|
|
41
|
+
# order is important!
|
42
|
+
LIST_METHOD_PREFIXES = %w[list describe get].freeze
|
43
|
+
|
44
|
+
def etype2method(etype)
|
45
|
+
LIST_METHOD_PREFIXES.each do |prefix|
|
46
|
+
m = "#{prefix}_#{etype}"
|
47
|
+
return m if client_class.public_method_defined?(m)
|
48
|
+
end
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def method2etype(method)
|
53
|
+
method.to_s.sub(/^(?:#{LIST_METHOD_PREFIXES.join("|")})_/, "")
|
54
|
+
end
|
55
|
+
|
35
56
|
def entity_types
|
36
57
|
methods = client_class
|
37
58
|
.instance_methods
|
38
|
-
.find_all { |m| m =~ /^(
|
59
|
+
.find_all { |m| m =~ /^(?:#{LIST_METHOD_PREFIXES.join("|")})_.+s$/ && m !~ /(?:status|access)$/ }
|
39
60
|
|
40
61
|
return [] if methods.empty?
|
41
62
|
|
@@ -44,10 +65,10 @@ module Lsaws
|
|
44
65
|
next(true) unless rdoc
|
45
66
|
|
46
67
|
required_params = rdoc.scan(/^\s+# @option params \[required, (.+?)\] :(\w+)/)
|
47
|
-
required_params.any?
|
68
|
+
required_params.any? || Lsaws.config.dig(@sdk, method2etype(m), "required_params")
|
48
69
|
end
|
49
70
|
|
50
|
-
methods.map { |m| m
|
71
|
+
methods.map { |m| method2etype(m) }.sort
|
51
72
|
end
|
52
73
|
|
53
74
|
def get_method_rdoc(method)
|
@@ -64,5 +85,10 @@ module Lsaws
|
|
64
85
|
end
|
65
86
|
chunk[chunk.rindex("\n\n") + 2..]
|
66
87
|
end
|
88
|
+
|
89
|
+
def get_method_api(method)
|
90
|
+
# calling private API!
|
91
|
+
client_class.api.operation(method)
|
92
|
+
end
|
67
93
|
end
|
68
94
|
end
|
data/lib/lsaws/version.rb
CHANGED
data/lib/lsaws.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "yaml"
|
4
|
+
|
3
5
|
module Lsaws
|
4
6
|
class Error < StandardError; end
|
5
7
|
|
6
8
|
def self.root
|
7
9
|
File.dirname(File.dirname(File.expand_path(__FILE__)))
|
8
10
|
end
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
@config ||= YAML.load_file(File.join(Lsaws.root, "lsaws.yml"))
|
14
|
+
end
|
9
15
|
end
|
10
16
|
|
11
17
|
require_relative "lsaws/version"
|
data/lsaws.yml
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lsaws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey "Zed" Zaikin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-core
|