aly 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="