aly 0.2.2 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 929950a91790b6ca3522f18cb114d29d58ccc1d4c61e4de6b649198d5624ecf3
4
- data.tar.gz: 0c55d48418ec5a8661f8ef912dc7fc647514c99be0c14964a2f2d7fb4ed78198
3
+ metadata.gz: 3a2457a76990e5b419f291514cc1fef338740d4d92ec8e1cafef0722f5a9e898
4
+ data.tar.gz: 976571d639a35952bde380eac487c4d4532f5746d8c5ce39acc62f8d31dbb2d7
5
5
  SHA512:
6
- metadata.gz: e3e21c88c0dc447b9ca035786bbe4f1c4504f148a7731cb9cc8b9d1205152392e5e83d7fb702aaefd6f20ffb5acea3fc22677f3bccd20332c0914391ceae2e30
7
- data.tar.gz: da9a871f358fa988084dc84f5498c3800bd6eefc8467dcae6faf81fc7f4a2aab60cc6128cf84d387103ff92b658611dda502c4a9f1beb2162100749a6dc0b3e8
6
+ metadata.gz: b243a6c0e3424e6078441fa504eedad8c88a32a032134a6494fc4fc40fa4819d030e1d26c2ae15a88754e4b8f7fa8d669c149b5322ecb8cf2929c41937074891
7
+ data.tar.gz: 1c8dcfa337ab879b1fa4d45b7e92686286fee9c04e79231277cf6d051cacfc1c3e28b720b0e6aa709fc5f418164377718a65240fe40fadcba35411779cec443b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- aly (0.2.2)
4
+ aly (0.3.1)
5
5
  terminal-table (~> 1.8.0)
6
6
  thor (~> 0.20.0)
7
7
 
data/aly.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "A simple wrapper for aliyun cli"
13
13
  spec.homepage = "https://github.com/lululau/aly"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
16
16
 
17
17
  # Specify which files should be added to the gem when it is released.
18
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
data/lib/aly/app.rb CHANGED
@@ -10,7 +10,7 @@ class Array
10
10
  Terminal::Table.new { |t|
11
11
  t << header
12
12
  t << :separator
13
- each { |row| t << row.values }
13
+ each { |row| t << (row.nil? ? :separator : row.values) }
14
14
  }
15
15
  end
16
16
  end
@@ -63,6 +63,7 @@ module Aly
63
63
  end
64
64
  end
65
65
 
66
+
66
67
  if options['detail']
67
68
  puts JSON.pretty_generate(selected)
68
69
  else
@@ -90,10 +91,136 @@ module Aly
90
91
  end
91
92
  end
92
93
 
94
+ def full_slb(lbs, eips, **options)
95
+ lbs.each do |lb|
96
+ puts "\nLoanBalancer Id: %s, Name: %s" % [lb['LoadBalancerId'], lb['LoadBalancerName']]
97
+ puts "==============================================================\n\n"
98
+ listeners = lb['Listeners']
99
+ background_servers = exec('slb', 'DescribeLoadBalancerAttribute', "--LoadBalancerId=#{lb['LoadBalancerId']}", **options)['BackendServers']['BackendServer'] || []
100
+
101
+ puts ' LoadBalancer Basic Information:'
102
+ puts([{
103
+ Id: lb['LoadBalancerId'],
104
+ Name: lb['LoadBalancerName'],
105
+ Address: lb['Address'],
106
+ Eip: lb['Eip'],
107
+ Listeners: listeners.size
108
+ }].table.to_s.gsub(/^/, ' '))
109
+ puts
110
+
111
+ if background_servers && background_servers.size > 0
112
+ puts ' Default Backend Servers:'
113
+ puts
114
+
115
+ ecss = @ecs.select { |e| background_servers.map{|ee| ee['ServerId']}.include?(e['InstanceId']) }
116
+
117
+ puts ecss.map { |row|
118
+ {
119
+ Id: row['InstanceId'],
120
+ Name: row['InstanceName'],
121
+ PrivateIP: row['PrivateIP'].join(','),
122
+ PublicIP: row['PublicIP'].join(','),
123
+ CPU: row['Cpu'],
124
+ RAM: "#{row['Memory'] / 1024.0} GB"
125
+ }
126
+ }.table.to_s.gsub(/^/, ' ')
127
+ puts
128
+ end
129
+
130
+ vserver_groups = exec('slb', 'DescribeVServerGroups', '--pager', "--LoadBalancerId=#{lb['LoadBalancerId']}", **options)["VServerGroups"]["VServerGroup"] || []
131
+ vserver_group_servers = vserver_groups.flat_map do |vg|
132
+ vg_attr = exec('slb', 'DescribeVServerGroupAttribute', "--VServerGroupId=#{vg['VServerGroupId']}", **options)["BackendServers"]["BackendServer"]
133
+ vg_attr.each_with_index.map do |attr, idx|
134
+ ecs = @ecs.find {|e| e['InstanceId'] == attr['ServerId'] }
135
+ {
136
+ VGroupId: (idx.zero? ? vg['VServerGroupId'] : ''),
137
+ VGroupName: (idx.zero? ? vg['VServerGroupName'] : ''),
138
+ Weight: attr['Weight'],
139
+ Port: attr['Port'],
140
+ Type: attr['Type'],
141
+ EcsId: attr['ServerId'],
142
+ EcsName: ecs['InstanceName'],
143
+ PrivateIP: ecs['PrivateIP'].join(','),
144
+ PublicIP: ecs['PublicIP'].join(','),
145
+ CPU: ecs['Cpu'],
146
+ RAM: "#{ecs['Memory'] / 1024.0} GB"
147
+ }
148
+ end + [nil]
149
+ end
150
+ puts ' VServer Groups:'
151
+ puts vserver_group_servers[0..-2].table.to_s.gsub(/^/, ' ')
152
+ puts
153
+
154
+ listeners.each do |listener|
155
+ listener_type = ['HTTP', 'HTTPS', 'TCP', 'TCPS', 'UDP'].find { |e| !listener["#{e}ListenerConfig"].empty? }
156
+ listener['ListenerType'] = listener_type
157
+ end
158
+
159
+ listeners_info = listeners.map do |listener|
160
+ {
161
+ Description: listener['Description'],
162
+ Port: listener['ListenerPort'],
163
+ Protocol: listener['ListenerProtocol'],
164
+ Status: listener['Status'],
165
+ HeathCheck: (listener["#{listener['ListenerType']}ListenerConfig"] || {}).dig("HealthCheck") || 'off',
166
+ BackendServerPort: listener['BackendServerPort'],
167
+ ForwardPort: listener.dig('HTTPListenerConfig', 'ForwardPort'),
168
+ VServerGroup: listener['VServerGroupId'],
169
+ AclStatus: listener['AclStatus'] || 'off',
170
+ AclType: listener['AclType'],
171
+ AclIds: (listener['AclIds'] || []).join(','),
172
+ }
173
+ end
174
+
175
+ puts ' Configured Listeners:'
176
+ puts listeners_info.table.to_s.gsub(/^/, ' ')
177
+ puts
178
+
179
+ listener_rules = listeners.flat_map do |listener|
180
+ listener_type = listener['ListenerType']
181
+ next [] unless listener_type
182
+ rules = exec('slb', "DescribeLoadBalancer#{listener_type}ListenerAttribute", "--LoadBalancerId=#{lb['LoadBalancerId']}", "--ListenerPort=#{listener['ListenerPort']}", **options).dig('Rules', 'Rule') || []
183
+ rules.map do |rule|
184
+ {'Listener' => listener['Description']}.merge(rule)
185
+ end
186
+ end
187
+
188
+ puts ' Listener Rules:'
189
+ puts listener_rules.table.to_s.gsub(/^/, ' ')
190
+ puts
191
+
192
+ if options['acl']
193
+ acl_ids = listeners.flat_map { |listener| listener['AclIds'] || [] }.uniq
194
+ unless acl_ids.empty?
195
+ alc_entries = acl_ids.flat_map do |acl_id|
196
+ attr = exec('slb', 'DescribeAccessControlListAttribute', "--AclId=#{acl_id}", **options)
197
+ (attr.dig('AclEntrys', 'AclEntry') || []).each_with_index.map do |e, idx|
198
+ {
199
+ AclId: (idx.zero? ? attr['AclId'] : ''),
200
+ AclName: (idx.zero? ? attr['AclName'] : ''),
201
+ AclEntryIP: e['AclEntryIP'],
202
+ AclEntryComment: e['AclEntryComment']
203
+ }
204
+ end + [nil]
205
+ end
206
+ puts ' Access Control Lists:'
207
+ puts alc_entries[0..-2].table.to_s.gsub(/^/, ' ')
208
+ puts
209
+ end
210
+
211
+ end
212
+
213
+ end
214
+ end
215
+
93
216
  def slb(*args, **options)
94
217
  raw_out = exec('slb', 'DescribeLoadBalancers', '--pager', **options)
95
218
  selected = raw_out['LoadBalancers']['LoadBalancer'] || []
96
219
 
220
+ eips = exec('vpc', 'DescribeEipAddresses', "--PageSize=#{selected.size}", **options)['EipAddresses']['EipAddress'].each_with_object({}) do |item, result|
221
+ result[item['InstanceId']] = item['IpAddress']
222
+ end
223
+
97
224
  listeners = (exec('slb', 'DescribeLoadBalancerListeners', '--pager', 'path=Listeners', **options)['Listeners'] || []).each_with_object({}) do |listener, result|
98
225
  instance_id = listener['LoadBalancerId']
99
226
  result[instance_id] ||= []
@@ -110,7 +237,29 @@ module Aly
110
237
  end
111
238
  end
112
239
 
113
- if options['detail']
240
+ @eip ||= exec('vpc', 'DescribeEipAddresses', '--PageSize=100', **options)['EipAddresses']['EipAddress'] || []
241
+
242
+ eip_map = @eip.each_with_object({}) { |eip, h| h[eip['InstanceId']] = eip['IpAddress'] }
243
+ selected.each do |slb|
244
+ slb['Eip'] = eip_map[slb['LoadBalancerId']]
245
+ end
246
+
247
+ @ecs = exec('ecs', 'DescribeInstances', '--pager', **options)['Instances']['Instance'] || []
248
+ @ecs.each do |item|
249
+ item['PrivateIP'] = (item['NetworkInterfaces']['NetworkInterface'] || []).map { |ni| ni['PrimaryIpAddress'] }
250
+ item['PublicIP'] = []
251
+ if ip = item['EipAddress']['IpAddress']
252
+ item['PublicIP'] << ip
253
+ end
254
+ if ips = item['PublicIpAddress']['IpAddress']
255
+ item['PublicIP'] += ips
256
+ end
257
+ item['AllIPs'] = item['PrivateIP'] + item['PublicIP']
258
+ end
259
+
260
+ if options['full']
261
+ full_slb(selected, eips, **options)
262
+ elsif options['detail']
114
263
  selected.each do |row|
115
264
  described_load_balancer_attributes = exec('slb', 'DescribeLoadBalancerAttribute', "--LoadBalancerId=#{row['LoadBalancerId']}", **options)
116
265
  row['BackendServers'] = described_load_balancer_attributes['BackendServers']['BackendServer']
@@ -140,6 +289,7 @@ module Aly
140
289
  Id: row['LoadBalancerId'],
141
290
  Name: row['LoadBalancerName'],
142
291
  Address: row['Address'],
292
+ Eip: eips[row['LoadBalancerId']] || '',
143
293
  Listeners: listeners
144
294
  }
145
295
  end
@@ -148,7 +298,7 @@ module Aly
148
298
  end
149
299
 
150
300
  def slb_contains_host?(host)
151
- @slb.any? { |lb| lb['Address'] == host }
301
+ @slb.any? { |lb| lb['Address'] == host || lb['Eip'] == host }
152
302
  end
153
303
 
154
304
  def ecs_contains_host?(host)
@@ -157,81 +307,124 @@ module Aly
157
307
 
158
308
  def show_slb(host, **options)
159
309
  @listeners ||= exec('slb', 'DescribeLoadBalancerListeners', '--pager', 'path=Listeners', **options)['Listeners'] || []
160
- lb = @slb.find { |e| e['Address'] == host }
310
+ lb = @slb.find { |e| e['Address'] == host || e['Eip'] == host }
161
311
  listeners = @listeners.select { |e| e['LoadBalancerId'] == lb['LoadBalancerId'] }
162
- background_servers = exec('slb', 'DescribeLoadBalancerAttribute', "--LoadBalancerId=#{lb['LoadBalancerId']}", **options)['BackendServers']['BackendServer']
163
312
 
164
- puts 'LoadBalancers:'
313
+ puts "\nLoanBalancer Id: %s, Name: %s" % [lb['LoadBalancerId'], lb['LoadBalancerName']]
314
+ puts "==============================================================\n\n"
315
+ background_servers = exec('slb', 'DescribeLoadBalancerAttribute', "--LoadBalancerId=#{lb['LoadBalancerId']}", **options)['BackendServers']['BackendServer'] || []
316
+
317
+ puts ' LoadBalancer Basic Information:'
165
318
  puts([{
166
- Id: lb['LoadBalancerId'],
167
- Name: lb['LoadBalancerName'],
168
- Address: lb['Address'],
169
- Listeners: listeners.size
170
- }].table.to_s)
319
+ Id: lb['LoadBalancerId'],
320
+ Name: lb['LoadBalancerName'],
321
+ Address: lb['Address'],
322
+ Eip: lb['Eip'],
323
+ Listeners: listeners.size
324
+ }].table.to_s.gsub(/^/, ' '))
171
325
  puts
172
326
 
173
327
  if background_servers && background_servers.size > 0
174
- puts 'Default Backend Servers:'
175
- puts background_servers.table.to_s
328
+ puts ' Default Backend Servers:'
329
+ puts
330
+
331
+ ecss = @ecs.select { |e| background_servers.map{|ee| ee['ServerId']}.include?(e['InstanceId']) }
332
+
333
+ puts ecss.map { |row|
334
+ {
335
+ Id: row['InstanceId'],
336
+ Name: row['InstanceName'],
337
+ PrivateIP: row['PrivateIP'].join(','),
338
+ PublicIP: row['PublicIP'].join(','),
339
+ CPU: row['Cpu'],
340
+ RAM: "#{row['Memory'] / 1024.0} GB"
341
+ }
342
+ }.table.to_s.gsub(/^/, ' ')
176
343
  puts
177
344
  end
178
345
 
346
+ vserver_groups = exec('slb', 'DescribeVServerGroups', '--pager', "--LoadBalancerId=#{lb['LoadBalancerId']}", **options)["VServerGroups"]["VServerGroup"] || []
347
+ vserver_group_servers = vserver_groups.flat_map do |vg|
348
+ vg_attr = exec('slb', 'DescribeVServerGroupAttribute', "--VServerGroupId=#{vg['VServerGroupId']}", **options)["BackendServers"]["BackendServer"]
349
+ vg_attr.each_with_index.map do |attr, idx|
350
+ ecs = @ecs.find {|e| e['InstanceId'] == attr['ServerId'] }
351
+ {
352
+ VGroupId: (idx.zero? ? vg['VServerGroupId'] : ''),
353
+ VGroupName: (idx.zero? ? vg['VServerGroupName'] : ''),
354
+ Weight: attr['Weight'],
355
+ Port: attr['Port'],
356
+ Type: attr['Type'],
357
+ EcsId: attr['ServerId'],
358
+ EcsName: ecs['InstanceName'],
359
+ PrivateIP: ecs['PrivateIP'].join(','),
360
+ PublicIP: ecs['PublicIP'].join(','),
361
+ CPU: ecs['Cpu'],
362
+ RAM: "#{ecs['Memory'] / 1024.0} GB"
363
+ }
364
+ end + [nil]
365
+ end
366
+ puts ' VServer Groups:'
367
+ puts vserver_group_servers[0..-2].table.to_s.gsub(/^/, ' ')
368
+ puts
369
+
370
+ listeners.each do |listener|
371
+ listener_type = ['HTTP', 'HTTPS', 'TCP', 'TCPS', 'UDP'].find { |e| !listener["#{e}ListenerConfig"].empty? }
372
+ listener['ListenerType'] = listener_type
373
+ end
374
+
179
375
  listeners_info = listeners.map do |listener|
180
376
  {
377
+ Description: listener['Description'],
181
378
  Port: listener['ListenerPort'],
182
379
  Protocol: listener['ListenerProtocol'],
183
380
  Status: listener['Status'],
381
+ HeathCheck: (listener["#{listener['ListenerType']}ListenerConfig"] || {}).dig("HealthCheck") || 'off',
184
382
  BackendServerPort: listener['BackendServerPort'],
185
383
  ForwardPort: listener.dig('HTTPListenerConfig', 'ForwardPort'),
186
- VServerGroup: listener['VServerGroupId']
384
+ VServerGroup: listener['VServerGroupId'],
385
+ AclStatus: listener['AclStatus'] || 'off',
386
+ AclType: listener['AclType'],
387
+ AclIds: (listener['AclIds'] || []).join(','),
187
388
  }
188
389
  end
189
390
 
190
- puts 'Configured Listeners:'
191
- puts listeners_info.table.to_s
391
+ puts ' Configured Listeners:'
392
+ puts listeners_info.table.to_s.gsub(/^/, ' ')
192
393
  puts
193
394
 
194
- listeners_info.each do |listener|
195
- if listener[:VServerGroup]
196
- vserver_group = exec('slb', 'DescribeVServerGroupAttribute', "--VServerGroupId=#{listener[:VServerGroup]}", **options)["BackendServers"]["BackendServer"]
197
- puts "VServerGroup #{listener[:VServerGroup]}:"
198
- puts(vserver_group.map { |e|
199
- {
200
- EcsInstanceId: e['ServerId'],
201
- Port: e['Port'],
202
- Weight: e['Weight'],
203
- Type: e['Type']
204
- }
205
- }.table.to_s)
206
- puts
395
+ listener_rules = listeners.flat_map do |listener|
396
+ listener_type = listener['ListenerType']
397
+ next [] unless listener_type
398
+ rules = exec('slb', "DescribeLoadBalancer#{listener_type}ListenerAttribute", "--LoadBalancerId=#{lb['LoadBalancerId']}", "--ListenerPort=#{listener['ListenerPort']}", **options).dig('Rules', 'Rule') || []
399
+ rules.map do |rule|
400
+ {'Listener' => listener['Description']}.merge(rule)
207
401
  end
208
402
  end
209
403
 
210
- ecs_ids = background_servers.map { |e| e['ServerId'] }
211
- ecs_ids += listeners_info.flat_map { |e|
212
- if e[:VServerGroup]
213
- exec('slb', 'DescribeVServerGroupAttribute', "--VServerGroupId=#{e[:VServerGroup]}", **options)["BackendServers"]["BackendServer"].map { |e| e['ServerId'] }
214
- else
215
- []
216
- end
217
- }
218
- ecs_ids.uniq!
219
-
220
- ecss = @ecs.select { |e| ecs_ids.include?(e['InstanceId']) }
221
-
222
- puts "Referenced ECS Instances:"
404
+ puts ' Listener Rules:'
405
+ puts listener_rules.table.to_s.gsub(/^/, ' ')
406
+ puts
223
407
 
224
- puts ecss.map { |row|
225
- {
226
- Id: row['InstanceId'],
227
- Name: row['InstanceName'],
228
- PrivateIP: row['PrivateIP'].join(','),
229
- PublicIP: row['PublicIP'].join(','),
230
- CPU: row['Cpu'],
231
- RAM: "#{row['Memory'] / 1024.0} GB"
232
- }
233
- }.table.to_s
408
+ if options['acl']
409
+ acl_ids = listeners.flat_map { |listener| listener['AclIds'] || [] }.uniq
410
+ unless acl_ids.empty?
411
+ alc_entries = acl_ids.flat_map do |acl_id|
412
+ attr = exec('slb', 'DescribeAccessControlListAttribute', "--AclId=#{acl_id}", **options)
413
+ (attr.dig('AclEntrys', 'AclEntry') || []).each_with_index.map do |e, idx|
414
+ {
415
+ AclId: (idx.zero? ? attr['AclId'] : ''),
416
+ AclName: (idx.zero? ? attr['AclName'] : ''),
417
+ AclEntryIP: e['AclEntryIP'],
418
+ AclEntryComment: e['AclEntryComment']
419
+ }
420
+ end + [nil]
421
+ end
422
+ puts ' Access Control Lists:'
423
+ puts alc_entries[0..-2].table.to_s.gsub(/^/, ' ')
424
+ puts
425
+ end
234
426
 
427
+ end
235
428
  end
236
429
 
237
430
  def show_ecs(host)
@@ -257,6 +450,12 @@ module Aly
257
450
  @slb ||= exec('slb', 'DescribeLoadBalancers', '--pager', **options)['LoadBalancers']['LoadBalancer'] || []
258
451
 
259
452
  @eip ||= exec('vpc', 'DescribeEipAddresses', '--PageSize=100', **options)['EipAddresses']['EipAddress'] || []
453
+
454
+ eip_map = @eip.each_with_object({}) { |eip, h| h[eip['InstanceId']] = eip['IpAddress'] }
455
+ @slb.each do |slb|
456
+ slb['Eip'] = eip_map[slb['LoadBalancerId']]
457
+ end
458
+
260
459
  unless @ecs
261
460
  @ecs = exec('ecs', 'DescribeInstances', '--pager', **options)['Instances']['Instance'] || []
262
461
  @ecs.each do |item|
@@ -282,7 +481,7 @@ module Aly
282
481
  elsif ecs_contains_host?(host)
283
482
  show_ecs(host)
284
483
  elsif eip_contains_host?(host)
285
- eip(host)
484
+ eip(host, **options)
286
485
  else
287
486
  puts "Not found: #{host}"
288
487
  end
data/lib/aly/cli.rb CHANGED
@@ -4,6 +4,8 @@ module Aly
4
4
  class CLI < ::Thor
5
5
  class_option :profile, type: :string, optional: true, aliases: ['-p'], desc: 'select profile'
6
6
  class_option :detail, type: :boolean, optional: true, default: false, aliases: ['-d'], desc: 'show detail infomation in JSON format'
7
+ class_option :full, type: :boolean, optional: true, default: false, aliases: ['-f'], desc: 'print tables with more infomation'
8
+ class_option :acl, type: :boolean, optional: true, default: false, aliases: ['-a'], desc: 'show ACL entries'
7
9
 
8
10
  desc 'ecs', 'get ECS information'
9
11
  def ecs(query = nil)
data/lib/aly/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aly
4
- VERSION = "0.2.2"
4
+ VERSION = "0.3.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Liu Xiang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-18 00:00:00.000000000 Z
11
+ date: 2022-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -88,7 +88,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
88
88
  requirements:
89
89
  - - ">="
90
90
  - !ruby/object:Gem::Version
91
- version: 2.7.0
91
+ version: 2.5.0
92
92
  required_rubygems_version: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="