Glavin001 / atom-beautify

:mega: Help Wanted - Looking for Maintainer: https://github.com/Glavin001/atom-beautify/issues/2572 | :lipstick: Universal beautification package for Atom editor (:warning: Currently migrating to https://github.com/Unibeautify/ and have very limited bandwidth for Atom-Beautify Issues. Thank you for your patience and understanding :heart: )
http://unibeautify.com/
MIT License
1.5k stars 453 forks source link

Lost first 330 Lines, after beautify #2596

Open rbur004 opened 3 years ago

rbur004 commented 3 years ago

Description

The first 330 lines of the file disappeared. I have only seen this on this one file. The others seem to be fine (Though I hope I haven't missed another case).

Running 'rubocop -a' directly on the file, does work as expected.

Input Before Beautification

This is what the code looked like before:

#!/usr/local/bin/ruby

# replacing config file driven LLDP scan with a DB driven one.

require 'ostruct'
require 'open3'
require 'wikk_configuration'
require 'wikk_sql'
require 'net/ssh'
require_relative '../rlib/rescue_msg.rb'

MYSQL_CONF = '/home/ubuntu/etc/netdb.conf'

def init_db
  @mysql_conf = WIKK::Configuration.new(MYSQL_CONF)
end

def init_switch_list
  @switch_list = {}
  WIKK::SQL::connect(@mysql_conf) do |sql|
    query = 'SELECT hostname, connection_name, manufacturer, model, os, host_id FROM host WHERE equipment_type = "switch"'
    sql.each_hash(query) do |row|
      @switch_list[row['hostname']] = row
    end
  end
end

def init_fields(s:, header:, debug: 0)
  puts "Line: #{s}" if debug >= 2
  puts "header: #{header}" if debug >= 2

  previous_index = nil
  field_range = {}
  header.each do |k| # Each key in the header
    field_start = s.index(k)
    return nil if field_start.nil? # Not a header line, or an incomplete one
    field_range[k] = [field_start,0]
    field_range[previous_index][1] = field_start - field_range[previous_index][0] unless previous_index.nil?    
    previous_index = k
  end
  # We don't know the end of the last field, as each line length will vary.
  field_range[previous_index][1] = 255 # Long past the end of the line. 

  if debug >= 2
    puts "Field [start, length]"
    p field_range
  end

  return field_range
end

=begin
  On OS9 switch 

h18x31#show interface port-channel brief 
=end

=begin
  On OS10 switch 

h18x46# show interface port-channel summary
=end

def parse_dell_line(l:, field_range:, debug: 0)
  # Split string into fields, based on the parsing the header
  # LAG     Mode      Status    Uptime              Ports

  p l if debug >= 2
  port = l.byteslice(* field_range['Ports'])
  return nil if port.nil?
  unless port.strip! == '' # Valid line check
    ps_start = port.rindex('(')
    ps_end = port.rindex(')')
    unless ps_start.nil? # Can get Port Channels that have no Port, so they have no status.
      lag = l.byteslice(* field_range['LAG']).strip
      mode = l.byteslice(* field_range['Mode']).strip
      pc_status = l.byteslice(* field_range['Status']).strip
      uptime = l.byteslice(* field_range['Uptime']).strip
      interface_status = port.byteslice( ps_start + 1, ps_end - ps_start - 1).strip # Up, Down, Inact
      port = port.byteslice( 0, ps_start ).strip
      return OpenStruct.new(lag: lag, 
                            mode: mode, 
                            pc_status: pc_status, 
                            ptime: uptime, 
                            port: port, 
                            interface_status: interface_status
                           ) 
    end
  end
  return nil # Not a valid line
end

=begin
  IBM switches
  'show lacp info' # Subset of 'show etherchannel summary'

  port    mode    adminkey  operkey   selected   prio  aggr  trunk  status  minlinks
  port left aligned             [1..n] and with the 1G switches [XGE1..4]
  mode left aligned             [active, passive, off]
  adminkey right aligned        iso.2.840.10006.300.43.1.2.1.1.6.p where p is the port number.
  operkey right aligned         iso.2.840.10006.300.43.1.2.1.1.7.p
  selected centered             [yes, no, suspended]
  prio right aligned            
  aggr right aligned
  trunk right aligned           Shows up in SNMP as the port channel, only if the LACP link is up.
  status centered               [up,down, --] 
  minlinks centered
=end

def parse_ibm_line(l:, field_range:, debug: 0)
  # Split string into fields, based on the parsing the header
  # Lists all interfaces on the switch, not just the ones set up with LACP

  p l if debug >= 2
  port = l.byteslice(* field_range['port'])  # Physical Interface on switch
  return nil if port.nil?

  port_names = []
  (1...48).each { |i| port_names << i.to_s}
  ['XGE1','XGE2','XGE3','XGE4'].each { |i| port_names << i.to_s}

  port.strip!
  if port_names.include?(port) # Valid line (we hope)
    lag = l.byteslice(* field_range['adminkey']).strip # Dell world, this would be the port channel number.
    mode = l.byteslice(* field_range['mode']).strip # active, passive, off i.e. LACP or not
    pc_status = l.byteslice(* field_range['trunk']).strip == '--' ? 'Down' : 'Up' # Only see a trunk if Up
    interface_status = l.byteslice(* field_range['status']).strip # up, down or -- if no LACP
    if mode == 'active' # We have an LACP port channel
      return OpenStruct.new(lag: lag, 
                            mode: mode, 
                            pc_status: pc_status, 
                            ptime: '', 
                            port: port, 
                            interface_status: interface_status
                           )
    else # Standard port
      return nil
    end
  end
  return nil # Not a valid line
end

def parse_query_result(s:, dell: true, host_id: nil, debug: 0)
  # Look for header line
  dell_headers = [ 'LAG','Mode','Status','Uptime','Ports']
  ibm_headers = [ 'port', 'mode', 'adminkey', 'operkey', ' selected', ' prio', 'aggr', 'trunk', 'status', 'minlinks' ]
  header = dell ? dell_headers : ibm_headers

  port_channel = {}
  field_range = nil
  last_pc = nil # Haven't seen a port channel line yet

  s.each_line do |l|
    if field_range.nil?
      field_range = init_fields(s: l.chomp, header: header, debug: debug)
    else
      fields = dell ? parse_dell_line(l: l.chomp, field_range: field_range, debug: debug) : parse_ibm_line(l: l.chomp, field_range: field_range, debug:debug)
      puts "Fields #{fields}" if debug >= 2
      unless fields.nil? #Good line
        if fields.lag != ''
          if port_channel[fields.lag].nil? 
            port_channel[fields.lag] ||= OpenStruct.new(status: fields.pc_status, interface: [fields], host_id: host_id)
            last_pc = fields
          else # IBM case, the lag is repeated. 
            port_channel[fields.lag].status = 'Up' if fields.pc_status == 'Up' # Any of the links being 'Up' overrides a 'Down' state
            port_channel[fields.lag].interface << fields
          end
        elsif last_pc != nil # Dell case, the lag is '', if not the first line for this lag
          port_channel[last_pc.lag].interface << fields
        else # Have a blank lag, but no previous lag entry, which shouldn't happen.
          warn("parse_query_result(s: #{s}, dell: #{dell}): Have a line with no LAG entry: #{l}")
        end
      end
    end
  end

  if debug >= 1
    port_channel.each do |lag, state|
      puts "port-channel: #{lag} status: #{state.status}"
      state.interface.each do |interface|
        puts "  interface: #{interface.port} status: #{interface.interface_status}"
      end
    end
  end

  return port_channel
end

KEYS=[ "/home/ubuntu/.ssh/ntr-switch-id_rsa", "/home/ubuntu/.ssh/x12_id_rsa"]
def ssh_host(host:, user: 'robot', key_type: :keys, key: KEYS, cmd: )
  begin
    # Need old encryption to talk to some of the switches
    kex = Net::SSH::Transport::Algorithms::ALGORITHMS[:kex] + %w(diffie-hellman-group1-sha1)
    encryption = Net::SSH::Transport::Algorithms::ALGORITHMS[:encryption] + %w(aes128-cbc)
    # Ignore the knownhosts file.
    Net::SSH.start(host, user, key_type => key, :verify_host_key => Net::SSH::Verifiers::Never.new, :encryption=>encryption, :kex => kex)       do |ssh|
        stdout = ""
        ssh.exec!(cmd) do |channel, stream, data|
          stdout << data if (stream == :stdout)
        end
        yield stdout
      end
    rescue StandardError => e
      rescue_msg(message: "ssh(#{host},#{cmd})", error: e)
      yield ""
    end
end

def lacp_status(switch_name:, switch_rec:, debug:)
  case switch_rec['os'] 
  when 'OS9'
    # VLTi ports included
    # Doesn't list ports that are down!
    command = 'show interface port-channel brief'
  when 'OS10.4','OS10.5'
    # VLTi ports excluded
    command =  'show interface port-channel summary'
  when '7.11.14.0' #G8052 and G8124 (which has extra lines in the output, ahead of the table)
    command = 'show lacp info' # Also 'show etherchannel summary'
  when '7.1.18.0' # Older G8000s. Requires password login.
    command = 'show lacp info' 
    # 'show interface link' equiv to Dell 'show interface status'
  end
  if switch_rec['model'] == 'G8000'
    ssh_host(host: switch_rec['connection_name'], cmd: command, key_type: :password, key: 'hytoffoo9876') do |o|
      return parse_query_result(s: o, dell: switch_rec['manufacturer'].downcase == 'dell', host_id: switch_rec['host_id'], debug: debug) unless o.nil?
    end
  else
    ssh_host(host: switch_rec['connection_name'], cmd: command) do |o|
      return parse_query_result(s: o, dell: switch_rec['manufacturer'].downcase == 'dell', host_id: switch_rec['host_id'], debug: debug) unless o.nil?
    end
  end
end

def test_parse
  port_channel_os9_test_data = <<-EOF
  Codes: L - LACP Port-channel
         O - OpenFlow Controller Port-channel
         A - Auto Port-channel
         I - Internally Lagged
      LAG  Mode  Status       Uptime      Ports          
      1    L2    up           12w6d2h     Fo 1/51    (Up)
                                          Fo 1/52    (Up)
  L   11   L2L3  up           4w2d19h     Te 1/12    (Up)
                                          Te 1/13    (Up)
  L   13   L2L3  up           4w2d19h     Te 1/14    (Up)
                                          Te 1/15    (Up)
  L   15   L2L3  up           4w5d8h      Te 1/16    (Up)
                                          Te 1/17    (Up)
  L   21   L2    up           4w4d2h      Te 1/1     (Up)
                                          Te 1/2     (Up)
  L   22   L2L3  up           4w3d2h      Te 1/3     (Up)
                                          Te 1/4     (Up)
  L   23   L2    up           4w5d8h      Te 1/5     (Up)
                                          Te 1/6     (Up)
  L   28   L2    up           4w5d8h      Te 1/7     (Up)
                                          Te 1/8     (Up)
  L   29   L2    up           4w3d7h      Te 1/9     (Up)
                                          Te 1/10    (Up)
  L   41   L2    up           4w2d19h     Te 1/22    (Up)
                                          Te 1/27    (Up)
  L   42   L2    up           4w2d19h     Te 1/26    (Up)
                                          Te 1/29    (Up)
  L   43   L2    up           4w2d19h     Te 1/28    (Up)
                                          Te 1/33    (Up)
  L   44   L2    up           4w3d0h      Te 1/32    (Up)
                                          Te 1/35    (Up)
  L   49   L2    up           4w3d5h      Te 1/18    (Up)
                                          Te 1/20    (Up)
  L   51   L2    up           4w2d19h     Te 1/38    (Up)
                                          Te 1/40    (Up)
  L   53   L2    up           4w3d0h      Te 1/34    (Up)
                                          Te 1/36    (Up)
  L   61   L2    up           4w2d19h     Te 1/25    (Up)
  L   62   L2    up           4w2d19h     Te 1/24    (Up)
  L   63   L2    up           4w2d22h     Te 1/31    (Up)
  L   64   L2    up           4w2d19h     Te 1/30    (Up)
  L   69   L2    up           4w3d0h      Te 1/11    (Up)
                                          Te 1/19    (Up)
  L   71   L2    up           4w5d8h      Te 1/41    (Up)
                                          Te 1/43    (Up)
  L   73   L2    up           4w3d2h      Te 1/37    (Up)
                                          Te 1/39    (Up)
  L   101  L2L3  up           12w5d19h    Fo 1/53    (Up)
                                          Fo 1/54    (Up)
  EOF

  parse_query_result(s: port_channel_os9_test_data, debug: 1)

  puts "*********"
  port_channel_os10_test_data = <<-EOF
  LAG     Mode      Status    Uptime              Ports
  101     L2-HYBRID up        5 days 03:19:25     Eth 1/1/1:1 (Up)
                                                  Eth 1/1/2:1 (Up)
  102     L2-HYBRID up        5 days 03:19:24     Eth 1/1/3:1 (Up)
                                                  Eth 1/1/4:1 (Up)
  103     L2-HYBRID up        5 days 03:19:23     Eth 1/1/5:1 (Up)
                                                  Eth 1/1/6:1 (Up)
  104     L2-HYBRID up        5 days 03:19:21     Eth 1/1/7 (Up)
                                                  Eth 1/1/8 (Up)
  105     L2-HYBRID up        5 days 03:19:19     Eth 1/1/9 (Up)
                                                  Eth 1/1/10 (Up)
  106     L2-HYBRID up        5 days 03:19:16     Eth 1/1/11 (Up)
                                                  Eth 1/1/12 (Up)
  107     L2-HYBRID down      00:00:00            Eth 1/1/13 (Down)
                                                  Eth 1/1/14 (Down)
  108     L2-HYBRID down      00:00:00            Eth 1/1/15 (Down)
                                                  Eth 1/1/16 (Down)
  109     L2-HYBRID down      00:00:00            Eth 1/1/17 (Down)
                                                  Eth 1/1/18 (Down)
  110     L2-HYBRID down      00:00:00            Eth 1/1/19 (Down)
                                                  Eth 1/1/20 (Down)
  111     L2-HYBRID down      00:00:00            Eth 1/1/21 (Down)
                                                  Eth 1/1/22 (Down)
  112     L2-HYBRID down      00:00:00            Eth 1/1/23 (Down)
                                                  Eth 1/1/24 (Down)
  113     L2-HYBRID down      00:00:00            Eth 1/1/25 (Down)
                                                  Eth 1/1/26 (Down)
  114     L2-HYBRID down      00:00:00            Eth 1/1/27 (Down)
                                                  Eth 1/1/28 (Down)
  115     L2-HYBRID down      00:00:00            Eth 1/1/29 (Down)
                                                  Eth 1/1/30 (Down)
  EOF

  parse_query_result(s: port_channel_os10_test_data, debug: 1)

  puts "*********"
  port_channel_ibm_test_data = <<-EOF
  ===========================================================
  port    mode    adminkey  operkey   selected   prio  aggr  trunk  status  minlinks
  ----------------------------------------------------------------------------------
  1       active         1        1     no      32768    --     --   down       1
  2       active         1        1     no      32768    --     --   down       1
  3       active         3        3     no      32768    --     --   down       1
  4       active         3        3     no      32768    --     --   down       1
  5       active         5        5     no      32768    --     --   down       1
  6       active         5        5     no      32768    --     --   down       1
  7       active         7        7     no      32768    --     --   down       1
  8       active         7        7     no      32768    --     --   down       1
  9       active         9        9    yes      32768     9     14    up        1
  10      active         9        9    yes      32768     9     14    up        1
  11      active        11       11     no      32768    --     --   down       1
  12      active        11       11  suspended  32768    --     --   down       1
  13      active        13       13  suspended  32768    --     --   down       1
  14      active        13       13  suspended  32768    --     --   down       1
  15      active        15       15    yes      32768    15     13    up        1
  16      active        15       15    yes      32768    15     13    up        1
  17      active        17       17    yes      32768    17     16    up        1
  18      active        17       17    yes      32768    17     16    up        1
  19      active        19       19    yes      32768    19     17    up        1
  20      active        19       19    yes      32768    19     17    up        1
  21      active        21       21  suspended  32768    --     --   down       1
  22      active        21       21  suspended  32768    --     --   down       1
  23      active       123      123    yes       4096    23     15    up        1
  24      active       123      123    yes       4096    23     15    up        1
  EOF

  parse_query_result(s: port_channel_ibm_test_data, dell: false, debug: 1)
  exit 0
end

def update_db(host_id:, interface:, field: , value:, debug: false)
  return if field.nil?
  WIKK::SQL::connect(@mysql_conf) do |sql|
    query = "UPDATE interface set interface.#{field} = #{value} 
             WHERE interface.host_id = #{host_id}
             AND interface.
            "
    puts query.gsub(/\n/, ' ') if debug
    return sql.query(query)
  end
end

def main(update_field: nil, debug: false)
  init_db
  init_switch_list
  @threads = []
  @switch_lacp_results = {}

  @switch_list.each do |switch_name, switch_rec|
    @threads << Thread.new(switch_name, switch_rec) do |sn, sr|
      @switch_lacp_results[sn] = lacp_status(switch_name: sn, switch_rec: sr, debug: 0)
    end

    if @threads.length == MAX_THREADS
      @threads.each { |thr| thr.join if thr != nil}
      @threads = []
    end
  end

  @threads.each { |thr| thr.join if thr != nil}

  @switch_lacp_results.sort.each do |switch_name, portchannel|
    puts "#{switch_name} (#{portchannel.host_id})" if debug
    portchannel.each do |lag, state|
      puts "port-channel: #{lag} status: #{state.status}" if debug
      state.interface.each do |interface|
        puts "  interface: #{interface.port} status: #{interface.interface_status}" if debug
        update_db(field: update_field, host_id: portchannel.host_id, debug: debug)
      end
    end
  end
end

debug = ARGV.include?('-d')

update_table = nil
field = nil
if ARGV.include?('-u')
  field = 'port_channel'
elsif ARGV.include?('-a')
  field = 'active_port_channel'
end

#test_parse
MAX_THREADS = 40

main(debug: debug, update_field: field)

Expected Output

The beautified code should have looked like this:

result of rubocop -a

#!/usr/local/bin/ruby

# replacing config file driven LLDP scan with a DB driven one.

require 'ostruct'
require 'open3'
require 'wikk_configuration'
require 'wikk_sql'
require 'net/ssh'
require_relative '../rlib/rescue_msg.rb'

MYSQL_CONF = '/home/ubuntu/etc/netdb.conf'

def init_db
  @mysql_conf = WIKK::Configuration.new(MYSQL_CONF)
end

def init_switch_list
  @switch_list = {}
  WIKK::SQL.connect(@mysql_conf) do |sql|
    query = 'SELECT hostname, connection_name, manufacturer, model, os, host_id FROM host WHERE equipment_type = "switch"'
    sql.each_hash(query) do |row|
      @switch_list[row['hostname']] = row
    end
  end
end

def init_fields(s:, header:, debug: 0)
  puts "Line: #{s}" if debug >= 2
  puts "header: #{header}" if debug >= 2

  previous_index = nil
  field_range = {}
  header.each do |k| # Each key in the header
    field_start = s.index(k)
    return nil if field_start.nil? # Not a header line, or an incomplete one

    field_range[k] = [ field_start, 0 ]
    field_range[previous_index][1] = field_start - field_range[previous_index][0] unless previous_index.nil?
    previous_index = k
  end
  # We don't know the end of the last field, as each line length will vary.
  field_range[previous_index][1] = 255 # Long past the end of the line.

  if debug >= 2
    puts 'Field [start, length]'
    p field_range
  end

  return field_range
end

#   On OS9 switch
#
# h18x31#show interface port-channel brief

#   On OS10 switch
#
# h18x46# show interface port-channel summary

def parse_dell_line(l:, field_range:, debug: 0)
  # Split string into fields, based on the parsing the header
  # LAG     Mode      Status    Uptime              Ports

  p l if debug >= 2
  port = l.byteslice(* field_range['Ports'])
  return nil if port.nil?

  unless port.strip! == '' # Valid line check
    ps_start = port.rindex('(')
    ps_end = port.rindex(')')
    unless ps_start.nil? # Can get Port Channels that have no Port, so they have no status.
      lag = l.byteslice(* field_range['LAG']).strip
      mode = l.byteslice(* field_range['Mode']).strip
      pc_status = l.byteslice(* field_range['Status']).strip
      uptime = l.byteslice(* field_range['Uptime']).strip
      interface_status = port.byteslice( ps_start + 1, ps_end - ps_start - 1).strip # Up, Down, Inact
      port = port.byteslice( 0, ps_start ).strip
      return OpenStruct.new(lag: lag,
                            mode: mode,
                            pc_status: pc_status,
                            ptime: uptime,
                            port: port,
                            interface_status: interface_status
                           )
    end
  end
  return nil # Not a valid line
end

#   IBM switches
#   'show lacp info' # Subset of 'show etherchannel summary'
#
#   port    mode    adminkey  operkey   selected   prio  aggr  trunk  status  minlinks
#   port left aligned             [1..n] and with the 1G switches [XGE1..4]
#   mode left aligned             [active, passive, off]
#   adminkey right aligned        iso.2.840.10006.300.43.1.2.1.1.6.p where p is the port number.
#   operkey right aligned         iso.2.840.10006.300.43.1.2.1.1.7.p
#   selected centered             [yes, no, suspended]
#   prio right aligned
#   aggr right aligned
#   trunk right aligned           Shows up in SNMP as the port channel, only if the LACP link is up.
#   status centered               [up,down, --]
#   minlinks centered

def parse_ibm_line(l:, field_range:, debug: 0)
  # Split string into fields, based on the parsing the header
  # Lists all interfaces on the switch, not just the ones set up with LACP

  p l if debug >= 2
  port = l.byteslice(* field_range['port'])  # Physical Interface on switch
  return nil if port.nil?

  port_names = []
  (1...48).each { |i| port_names << i.to_s }
  [ 'XGE1', 'XGE2', 'XGE3', 'XGE4' ].each { |i| port_names << i.to_s }

  port.strip!
  if port_names.include?(port) # Valid line (we hope)
    lag = l.byteslice(* field_range['adminkey']).strip # Dell world, this would be the port channel number.
    mode = l.byteslice(* field_range['mode']).strip # active, passive, off i.e. LACP or not
    pc_status = l.byteslice(* field_range['trunk']).strip == '--' ? 'Down' : 'Up' # Only see a trunk if Up
    interface_status = l.byteslice(* field_range['status']).strip # up, down or -- if no LACP
    if mode == 'active' # We have an LACP port channel
      return OpenStruct.new(lag: lag,
                            mode: mode,
                            pc_status: pc_status,
                            ptime: '',
                            port: port,
                            interface_status: interface_status
                           )
    else # Standard port
      return nil
    end
  end
  return nil # Not a valid line
end

def parse_query_result(s:, dell: true, host_id: nil, debug: 0)
  # Look for header line
  dell_headers = [ 'LAG', 'Mode', 'Status', 'Uptime', 'Ports' ]
  ibm_headers = [ 'port', 'mode', 'adminkey', 'operkey', ' selected', ' prio', 'aggr', 'trunk', 'status', 'minlinks' ]
  header = dell ? dell_headers : ibm_headers

  port_channel = {}
  field_range = nil
  last_pc = nil # Haven't seen a port channel line yet

  s.each_line do |l|
    if field_range.nil?
      field_range = init_fields(s: l.chomp, header: header, debug: debug)
    else
      fields = dell ? parse_dell_line(l: l.chomp, field_range: field_range, debug: debug) : parse_ibm_line(l: l.chomp, field_range: field_range, debug: debug)
      puts "Fields #{fields}" if debug >= 2
      unless fields.nil? # Good line
        if fields.lag != ''
          if port_channel[fields.lag].nil?
            port_channel[fields.lag] ||= OpenStruct.new(status: fields.pc_status, interface: [ fields ], host_id: host_id)
            last_pc = fields
          else # IBM case, the lag is repeated.
            port_channel[fields.lag].status = 'Up' if fields.pc_status == 'Up' # Any of the links being 'Up' overrides a 'Down' state
            port_channel[fields.lag].interface << fields
          end
        elsif last_pc != nil # Dell case, the lag is '', if not the first line for this lag
          port_channel[last_pc.lag].interface << fields
        else # Have a blank lag, but no previous lag entry, which shouldn't happen.
          warn("parse_query_result(s: #{s}, dell: #{dell}): Have a line with no LAG entry: #{l}")
        end
      end
    end
  end

  if debug >= 1
    port_channel.each do |lag, state|
      puts "port-channel: #{lag} status: #{state.status}"
      state.interface.each do |interface|
        puts "  interface: #{interface.port} status: #{interface.interface_status}"
      end
    end
  end

  return port_channel
end

KEYS = [ '/home/ubuntu/.ssh/ntr-switch-id_rsa', '/home/ubuntu/.ssh/x12_id_rsa' ]
def ssh_host(host:, cmd:, user: 'robot', key_type: :keys, key: KEYS)
  begin
    # Need old encryption to talk to some of the switches
    kex = Net::SSH::Transport::Algorithms::ALGORITHMS[:kex] + [ 'diffie-hellman-group1-sha1' ]
    encryption = Net::SSH::Transport::Algorithms::ALGORITHMS[:encryption] + [ 'aes128-cbc' ]
    # Ignore the knownhosts file.
    Net::SSH.start(host, user, key_type => key, :verify_host_key => Net::SSH::Verifiers::Never.new, :encryption => encryption, :kex => kex) do |ssh|
      stdout = ''
      ssh.exec!(cmd) do |_channel, stream, data|
        stdout << data if stream == :stdout
      end
      yield stdout
    end
  rescue StandardError => e
    rescue_msg(message: "ssh(#{host},#{cmd})", error: e)
    yield ''
  end
end

def lacp_status(switch_name:, switch_rec:, debug:)
  case switch_rec['os']
  when 'OS9'
    # VLTi ports included
    # Doesn't list ports that are down!
    command = 'show interface port-channel brief'
  when 'OS10.4', 'OS10.5'
    # VLTi ports excluded
    command = 'show interface port-channel summary'
  when '7.11.14.0' # G8052 and G8124 (which has extra lines in the output, ahead of the table)
    command = 'show lacp info' # Also 'show etherchannel summary'
  when '7.1.18.0' # Older G8000s. Requires password login.
    command = 'show lacp info'
    # 'show interface link' equiv to Dell 'show interface status'
  end
  if switch_rec['model'] == 'G8000'
    ssh_host(host: switch_rec['connection_name'], cmd: command, key_type: :password, key: 'hytoffoo9876') do |o|
      return parse_query_result(s: o, dell: switch_rec['manufacturer'].downcase == 'dell', host_id: switch_rec['host_id'], debug: debug) unless o.nil?
    end
  else
    ssh_host(host: switch_rec['connection_name'], cmd: command) do |o|
      return parse_query_result(s: o, dell: switch_rec['manufacturer'].downcase == 'dell', host_id: switch_rec['host_id'], debug: debug) unless o.nil?
    end
  end
end

def test_parse
  port_channel_os9_test_data = <<-EOF
  Codes: L - LACP Port-channel
         O - OpenFlow Controller Port-channel
         A - Auto Port-channel
         I - Internally Lagged
      LAG  Mode  Status       Uptime      Ports#{'          '}
      1    L2    up           12w6d2h     Fo 1/51    (Up)
                                          Fo 1/52    (Up)
  L   11   L2L3  up           4w2d19h     Te 1/12    (Up)
                                          Te 1/13    (Up)
  L   13   L2L3  up           4w2d19h     Te 1/14    (Up)
                                          Te 1/15    (Up)
  L   15   L2L3  up           4w5d8h      Te 1/16    (Up)
                                          Te 1/17    (Up)
  L   21   L2    up           4w4d2h      Te 1/1     (Up)
                                          Te 1/2     (Up)
  L   22   L2L3  up           4w3d2h      Te 1/3     (Up)
                                          Te 1/4     (Up)
  L   23   L2    up           4w5d8h      Te 1/5     (Up)
                                          Te 1/6     (Up)
  L   28   L2    up           4w5d8h      Te 1/7     (Up)
                                          Te 1/8     (Up)
  L   29   L2    up           4w3d7h      Te 1/9     (Up)
                                          Te 1/10    (Up)
  L   41   L2    up           4w2d19h     Te 1/22    (Up)
                                          Te 1/27    (Up)
  L   42   L2    up           4w2d19h     Te 1/26    (Up)
                                          Te 1/29    (Up)
  L   43   L2    up           4w2d19h     Te 1/28    (Up)
                                          Te 1/33    (Up)
  L   44   L2    up           4w3d0h      Te 1/32    (Up)
                                          Te 1/35    (Up)
  L   49   L2    up           4w3d5h      Te 1/18    (Up)
                                          Te 1/20    (Up)
  L   51   L2    up           4w2d19h     Te 1/38    (Up)
                                          Te 1/40    (Up)
  L   53   L2    up           4w3d0h      Te 1/34    (Up)
                                          Te 1/36    (Up)
  L   61   L2    up           4w2d19h     Te 1/25    (Up)
  L   62   L2    up           4w2d19h     Te 1/24    (Up)
  L   63   L2    up           4w2d22h     Te 1/31    (Up)
  L   64   L2    up           4w2d19h     Te 1/30    (Up)
  L   69   L2    up           4w3d0h      Te 1/11    (Up)
                                          Te 1/19    (Up)
  L   71   L2    up           4w5d8h      Te 1/41    (Up)
                                          Te 1/43    (Up)
  L   73   L2    up           4w3d2h      Te 1/37    (Up)
                                          Te 1/39    (Up)
  L   101  L2L3  up           12w5d19h    Fo 1/53    (Up)
                                          Fo 1/54    (Up)
  EOF

  parse_query_result(s: port_channel_os9_test_data, debug: 1)

  puts '*********'
  port_channel_os10_test_data = <<-EOF
  LAG     Mode      Status    Uptime              Ports
  101     L2-HYBRID up        5 days 03:19:25     Eth 1/1/1:1 (Up)
                                                  Eth 1/1/2:1 (Up)
  102     L2-HYBRID up        5 days 03:19:24     Eth 1/1/3:1 (Up)
                                                  Eth 1/1/4:1 (Up)
  103     L2-HYBRID up        5 days 03:19:23     Eth 1/1/5:1 (Up)
                                                  Eth 1/1/6:1 (Up)
  104     L2-HYBRID up        5 days 03:19:21     Eth 1/1/7 (Up)
                                                  Eth 1/1/8 (Up)
  105     L2-HYBRID up        5 days 03:19:19     Eth 1/1/9 (Up)
                                                  Eth 1/1/10 (Up)
  106     L2-HYBRID up        5 days 03:19:16     Eth 1/1/11 (Up)
                                                  Eth 1/1/12 (Up)
  107     L2-HYBRID down      00:00:00            Eth 1/1/13 (Down)
                                                  Eth 1/1/14 (Down)
  108     L2-HYBRID down      00:00:00            Eth 1/1/15 (Down)
                                                  Eth 1/1/16 (Down)
  109     L2-HYBRID down      00:00:00            Eth 1/1/17 (Down)
                                                  Eth 1/1/18 (Down)
  110     L2-HYBRID down      00:00:00            Eth 1/1/19 (Down)
                                                  Eth 1/1/20 (Down)
  111     L2-HYBRID down      00:00:00            Eth 1/1/21 (Down)
                                                  Eth 1/1/22 (Down)
  112     L2-HYBRID down      00:00:00            Eth 1/1/23 (Down)
                                                  Eth 1/1/24 (Down)
  113     L2-HYBRID down      00:00:00            Eth 1/1/25 (Down)
                                                  Eth 1/1/26 (Down)
  114     L2-HYBRID down      00:00:00            Eth 1/1/27 (Down)
                                                  Eth 1/1/28 (Down)
  115     L2-HYBRID down      00:00:00            Eth 1/1/29 (Down)
                                                  Eth 1/1/30 (Down)
  EOF

  parse_query_result(s: port_channel_os10_test_data, debug: 1)

  puts '*********'
  port_channel_ibm_test_data = <<-EOF
  ===========================================================
  port    mode    adminkey  operkey   selected   prio  aggr  trunk  status  minlinks
  ----------------------------------------------------------------------------------
  1       active         1        1     no      32768    --     --   down       1
  2       active         1        1     no      32768    --     --   down       1
  3       active         3        3     no      32768    --     --   down       1
  4       active         3        3     no      32768    --     --   down       1
  5       active         5        5     no      32768    --     --   down       1
  6       active         5        5     no      32768    --     --   down       1
  7       active         7        7     no      32768    --     --   down       1
  8       active         7        7     no      32768    --     --   down       1
  9       active         9        9    yes      32768     9     14    up        1
  10      active         9        9    yes      32768     9     14    up        1
  11      active        11       11     no      32768    --     --   down       1
  12      active        11       11  suspended  32768    --     --   down       1
  13      active        13       13  suspended  32768    --     --   down       1
  14      active        13       13  suspended  32768    --     --   down       1
  15      active        15       15    yes      32768    15     13    up        1
  16      active        15       15    yes      32768    15     13    up        1
  17      active        17       17    yes      32768    17     16    up        1
  18      active        17       17    yes      32768    17     16    up        1
  19      active        19       19    yes      32768    19     17    up        1
  20      active        19       19    yes      32768    19     17    up        1
  21      active        21       21  suspended  32768    --     --   down       1
  22      active        21       21  suspended  32768    --     --   down       1
  23      active       123      123    yes       4096    23     15    up        1
  24      active       123      123    yes       4096    23     15    up        1
  EOF

  parse_query_result(s: port_channel_ibm_test_data, dell: false, debug: 1)
  exit 0
end

def update_db(host_id:, interface:, field:, value:, debug: false)
  return if field.nil?

  WIKK::SQL.connect(@mysql_conf) do |sql|
    query = "UPDATE interface set interface.#{field} = #{value}
             WHERE interface.host_id = #{host_id}
             AND interface.
            "
    puts query.gsub(/\n/, ' ') if debug
    return sql.query(query)
  end
end

def main(update_field: nil, debug: false)
  init_db
  init_switch_list
  @threads = []
  @switch_lacp_results = {}

  @switch_list.each do |switch_name, switch_rec|
    @threads << Thread.new(switch_name, switch_rec) do |sn, sr|
      @switch_lacp_results[sn] = lacp_status(switch_name: sn, switch_rec: sr, debug: 0)
    end

    if @threads.length == MAX_THREADS
      @threads.each { |thr| thr.join if thr != nil }
      @threads = []
    end
  end

  @threads.each { |thr| thr.join if thr != nil }

  @switch_lacp_results.sort.each do |switch_name, portchannel|
    puts "#{switch_name} (#{portchannel.host_id})" if debug
    portchannel.each do |lag, state|
      puts "port-channel: #{lag} status: #{state.status}" if debug
      state.interface.each do |interface|
        puts "  interface: #{interface.port} status: #{interface.interface_status}" if debug
        update_db(field: update_field, host_id: portchannel.host_id, debug: debug)
      end
    end
  end
end

debug = ARGV.include?('-d')

update_table = nil
field = nil
if ARGV.include?('-u')
  field = 'port_channel'
elsif ARGV.include?('-a')
  field = 'active_port_channel'
end

# test_parse
MAX_THREADS = 40

main(debug: debug, update_field: field)

Actual Output

The beautified code actually looked like this: Every line, upto line 331 is gone!

  port    mode    adminkey  operkey   selected   prio  aggr  trunk  status  minlinks
  ----------------------------------------------------------------------------------
  1       active         1        1     no      32768    --     --   down       1
  2       active         1        1     no      32768    --     --   down       1
  3       active         3        3     no      32768    --     --   down       1
  4       active         3        3     no      32768    --     --   down       1
  5       active         5        5     no      32768    --     --   down       1
  6       active         5        5     no      32768    --     --   down       1
  7       active         7        7     no      32768    --     --   down       1
  8       active         7        7     no      32768    --     --   down       1
  9       active         9        9    yes      32768     9     14    up        1
  10      active         9        9    yes      32768     9     14    up        1
  11      active        11       11     no      32768    --     --   down       1
  12      active        11       11  suspended  32768    --     --   down       1
  13      active        13       13  suspended  32768    --     --   down       1
  14      active        13       13  suspended  32768    --     --   down       1
  15      active        15       15    yes      32768    15     13    up        1
  16      active        15       15    yes      32768    15     13    up        1
  17      active        17       17    yes      32768    17     16    up        1
  18      active        17       17    yes      32768    17     16    up        1
  19      active        19       19    yes      32768    19     17    up        1
  20      active        19       19    yes      32768    19     17    up        1
  21      active        21       21  suspended  32768    --     --   down       1
  22      active        21       21  suspended  32768    --     --   down       1
  23      active       123      123    yes       4096    23     15    up        1
  24      active       123      123    yes       4096    23     15    up        1
  EOF

  parse_query_result(s: port_channel_ibm_test_data, dell: false, debug: 1)
  exit 0
end

def update_db(host_id:, interface:, field:, value:, debug: false)
  return if field.nil?

  WIKK::SQL.connect(@mysql_conf) do |sql|
    query = "UPDATE interface set interface.#{field} = #{value}
             WHERE interface.host_id = #{host_id}
             AND interface.
            "
    puts query.gsub(/\n/, ' ') if debug
    return sql.query(query)
  end
end

def main(update_field: nil, debug: false)
  init_db
  init_switch_list
  @threads = []
  @switch_lacp_results = {}

  @switch_list.each do |switch_name, switch_rec|
    @threads << Thread.new(switch_name, switch_rec) do |sn, sr|
      @switch_lacp_results[sn] = lacp_status(switch_name: sn, switch_rec: sr, debug: 0)
    end

    if @threads.length == MAX_THREADS
      @threads.each { |thr| thr.join if thr != nil }
      @threads = []
    end
  end

  @threads.each { |thr| thr.join if thr != nil }

  @switch_lacp_results.sort.each do |switch_name, portchannel|
    puts "#{switch_name} (#{portchannel.host_id})" if debug
    portchannel.each do |lag, state|
      puts "port-channel: #{lag} status: #{state.status}" if debug
      state.interface.each do |interface|
        puts "  interface: #{interface.port} status: #{interface.interface_status}" if debug
        update_db(field: update_field, host_id: portchannel.host_id, debug: debug)
      end
    end
  end
end

debug = ARGV.include?('-d')

update_table = nil
field = nil
if ARGV.include?('-u')
  field = 'port_channel'
elsif ARGV.include?('-a')
  field = 'active_port_channel'
end

# test_parse
MAX_THREADS = 40

main(debug: debug, update_field: field)

Steps to Reproduce

  1. Add code to Atom editor
  2. Run command Atom Beautify: Beautify Editor
  3. This beautified code does not look right!

Debug

Here is a link to the debug.md Gist: https://github.com/rbur004/atom_beautifier_gist/blob/main/debug.md

Checklist

I have:

SilentGlasses commented 1 year ago

If you still need this and are looking for something to fill the spot that Atom left, I am using Pulsar the successor to Atom... This package is working except for one deprecated error listed in #2605

If you don't need this anymore, can you please close this out so it's not just sitting there? Thanks