mirror of
https://github.com/xcat2/confluent.git
synced 2025-04-13 16:57:59 +00:00
Implement collate command
Also adjust output to be less buffered for sake of '-w' and other pipe commands.
This commit is contained in:
parent
87da7b62ae
commit
a571faa215
76
confluent_client/bin/collate
Normal file
76
confluent_client/bin/collate
Normal file
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2017 Lenovo
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# This is a utility to bring xcoll (plus enhancements) to confluent
|
||||
# the core engine is textgroup.py, this simply provides a CLI to use
|
||||
# generically
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
path = os.path.realpath(os.path.join(path, '..', 'lib', 'python'))
|
||||
if path.startswith('/opt'):
|
||||
sys.path.append(path)
|
||||
|
||||
import confluent.textgroup as tg
|
||||
|
||||
argparser = optparse.OptionParser(usage="Usage: <other command> | %prog [options]")
|
||||
argparser.add_option('-d', '--diff', action='store_true',
|
||||
help='Show what differs between most common '
|
||||
'output group and others')
|
||||
argparser.add_option('-w', '--watch', action='store_true',
|
||||
help='Show intermediate results while running')
|
||||
argparser.add_option('-s', '--skipcommon', action='store_true',
|
||||
help='Do not print most common result, only non modal '
|
||||
'groups, useful when combined with -d')
|
||||
argparser.add_option('-c', '--count', action='store_true',
|
||||
help='Also display count of nodes in a given group')
|
||||
argparser.add_option('-r', '--reverse', action='store_true',
|
||||
help='Reverse sort order to show biggest output group '
|
||||
'last')
|
||||
(options, args) = argparser.parse_args()
|
||||
if sys.stdin.isatty():
|
||||
argparser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
grouped = tg.GroupedData()
|
||||
|
||||
def print_current():
|
||||
if options.diff:
|
||||
grouped.print_deviants(skipmodal=options.skipcommon, count=options.count,
|
||||
reverse=options.reverse)
|
||||
else:
|
||||
grouped.print_all(skipmodal=options.skipcommon,
|
||||
count=options.count,
|
||||
reverse=options.reverse)
|
||||
sys.stdout.flush()
|
||||
|
||||
fullline = sys.stdin.readline()
|
||||
while fullline:
|
||||
for line in fullline.split('\n'):
|
||||
if not line:
|
||||
continue
|
||||
grouped.add_line(*line.split(': ', 1))
|
||||
if options.watch:
|
||||
sys.stdout.write('\x1b[2J\x1b[;H') # clear screen
|
||||
print_current()
|
||||
fullline = sys.stdin.readline()
|
||||
if not options.watch:
|
||||
print_current()
|
||||
|
@ -83,8 +83,10 @@ def run():
|
||||
node = desc['node']
|
||||
if desc['type'] == 'stdout':
|
||||
sys.stdout.write('{0}: {1}'.format(node,data))
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
sys.stderr.write('{0}: {1}'.format(node, data))
|
||||
sys.stderr.flush()
|
||||
else:
|
||||
pop = desc['popen']
|
||||
ret = pop.poll()
|
||||
|
@ -146,6 +146,7 @@ def sensorpass(showout=True, appendtime=False):
|
||||
'%Y-%m-%dT%H:%M:%S')
|
||||
print(u'{0}: {1}:{2}'.format(
|
||||
node, sensedata['name'], showval).encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
return resultdata
|
||||
|
||||
|
||||
|
@ -83,8 +83,10 @@ def run():
|
||||
node = desc['node']
|
||||
if desc['type'] == 'stdout':
|
||||
sys.stdout.write('{0}: {1}'.format(node,data))
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
sys.stderr.write('{0}: {1}'.format(node, data))
|
||||
sys.stderr.flush()
|
||||
else:
|
||||
pop = desc['popen']
|
||||
ret = pop.poll()
|
||||
|
@ -27,6 +27,10 @@ import confluent.tlvdata as tlvdata
|
||||
SO_PASSCRED = 16
|
||||
|
||||
|
||||
def cprint(txt):
|
||||
print(txt)
|
||||
sys.stdout.flush()
|
||||
|
||||
def _parseserver(string):
|
||||
if ']:' in string:
|
||||
server, port = string[1:].split(']:')
|
||||
@ -105,10 +109,10 @@ class Command(object):
|
||||
else:
|
||||
val = repr(res[node][ikey])
|
||||
if self._prevkeyname and self._prevkeyname in res[node]:
|
||||
print('{0}: {2}->{1}'.format(
|
||||
cprint('{0}: {2}->{1}'.format(
|
||||
node, val, res[node][self._prevkeyname]['value']))
|
||||
else:
|
||||
print('{0}: {1}'.format(node, val))
|
||||
cprint('{0}: {1}'.format(node, val))
|
||||
return rc
|
||||
|
||||
def simple_noderange_command(self, noderange, resource, input=None,
|
||||
@ -133,7 +137,7 @@ class Command(object):
|
||||
rc = self.handle_results(ikey, rc, res, errnodes)
|
||||
return rc
|
||||
except KeyboardInterrupt:
|
||||
print('')
|
||||
cprint('')
|
||||
return 0
|
||||
|
||||
def simple_nodegroups_command(self, noderange, resource, input=None, key=None, **kwargs):
|
||||
@ -157,7 +161,7 @@ class Command(object):
|
||||
rc = self.handle_results(ikey, rc, res)
|
||||
return rc
|
||||
except KeyboardInterrupt:
|
||||
print('')
|
||||
cprint('')
|
||||
return 0
|
||||
|
||||
def read(self, path, parameters=None):
|
||||
@ -239,7 +243,7 @@ class Command(object):
|
||||
"MISMATCHED CERTIFICATE DATA, ACCEPT NEW? (y/n):")
|
||||
if replace not in ('y', 'Y'):
|
||||
raise Exception("BAD CERTIFICATE")
|
||||
print 'Adding new key for %s:%s' % (server, port)
|
||||
cprint('Adding new key for %s:%s' % (server, port))
|
||||
khf[hostid] = fingerprint
|
||||
|
||||
|
||||
@ -318,7 +322,7 @@ def printattributes(session, requestargs, showtype, nodetype, noderange, options
|
||||
dictout.append("{0}={1}".format(k, v))
|
||||
attrout = '{0}: {1}: {2}'.format(node, attr, ','.join(map(str, dictout)))
|
||||
else:
|
||||
print ("CODE ERROR" + repr(attr))
|
||||
cprint("CODE ERROR" + repr(attr))
|
||||
|
||||
if options.blame or 'broken' in currattr:
|
||||
blamedata = []
|
||||
@ -332,7 +336,7 @@ def printattributes(session, requestargs, showtype, nodetype, noderange, options
|
||||
currattr['expression']))
|
||||
if blamedata:
|
||||
attrout += ' (' + ', '.join(blamedata) + ')'
|
||||
print attrout
|
||||
cprint(attrout)
|
||||
if not exitcode:
|
||||
if requestargs:
|
||||
for attr in requestargs:
|
||||
@ -379,8 +383,8 @@ def printgroupattributes(session, requestargs, showtype, nodetype, noderange, op
|
||||
dictout.append("{0}={1}".format(k, v))
|
||||
attrout = '{0}: {1}: {2}'.format(noderange, attr, ','.join(map(str, dictout)))
|
||||
else:
|
||||
print ("CODE ERROR" + repr(attr))
|
||||
print attrout
|
||||
cprint("CODE ERROR" + repr(attr))
|
||||
cprint(attrout)
|
||||
if not exitcode:
|
||||
if requestargs:
|
||||
for attr in requestargs:
|
||||
|
@ -73,10 +73,41 @@ class GroupedData(object):
|
||||
else:
|
||||
self.bynode[node].append(line)
|
||||
|
||||
def print_deviants(self, output=sys.stdout, skipmodal=True):
|
||||
def print_all(self, output=sys.stdout, skipmodal=False, reverse=False,
|
||||
count=False):
|
||||
self.generate_byoutput()
|
||||
modaloutput = None
|
||||
ismodal = True
|
||||
outdatalist = sorted(
|
||||
self.byoutput, key=lambda x: len(self.byoutput[x]))
|
||||
if not reverse:
|
||||
outdatalist = reversed(outdatalist)
|
||||
if reverse and skipmodal:
|
||||
# if reversed, the last is biggest and should be skipped if modal
|
||||
outdatalist = outdatalist[:-1]
|
||||
for outdata in outdatalist:
|
||||
if not reverse and skipmodal:
|
||||
# If big first, this makes skipmodal skip first
|
||||
skipmodal = False
|
||||
continue
|
||||
currout = '====================================\n'
|
||||
currout += ','.join(sorted(self.byoutput[outdata]))
|
||||
currout += '\n====================================\n'
|
||||
if count:
|
||||
currout += 'Count: {0}'.format(len(list(
|
||||
self.byoutput[outdata])))
|
||||
currout += '\n====================================\n'
|
||||
currout += outdata
|
||||
currout += '\n\n'
|
||||
output.write(currout)
|
||||
output.flush()
|
||||
|
||||
def print_deviants(self, output=sys.stdout, skipmodal=False, reverse=False,
|
||||
count=False):
|
||||
self.generate_byoutput()
|
||||
modaloutput = None
|
||||
ismodal = True
|
||||
revoutput = []
|
||||
for outdata in reversed(
|
||||
sorted(self.byoutput, key=lambda x: len(self.byoutput[x]))):
|
||||
if modaloutput is None:
|
||||
@ -85,16 +116,26 @@ class GroupedData(object):
|
||||
skipmodal = False
|
||||
ismodal = False
|
||||
continue
|
||||
output.write('====================================\n')
|
||||
output.write(','.join(sorted(self.byoutput[outdata])))
|
||||
output.write('\n====================================\n')
|
||||
currout = '====================================\n'
|
||||
currout += ','.join(sorted(self.byoutput[outdata]))
|
||||
currout += '\n====================================\n'
|
||||
if count:
|
||||
currout += 'Count: {0}'.format(len(list(
|
||||
self.byoutput[outdata])))
|
||||
currout += '\n====================================\n'
|
||||
if ismodal:
|
||||
ismodal = False
|
||||
output.write(outdata)
|
||||
currout += outdata
|
||||
else:
|
||||
output.write('\n'.join(colordiff(modaloutput.split('\n'),
|
||||
outdata.split('\n'))))
|
||||
output.write('\n\n')
|
||||
currout += '\n'.join(colordiff(modaloutput.split('\n'),
|
||||
outdata.split('\n')))
|
||||
currout += '\n\n'
|
||||
if reverse:
|
||||
revoutput.append(currout)
|
||||
else:
|
||||
output.write(currout)
|
||||
for currout in reversed(revoutput):
|
||||
output.write(currout)
|
||||
output.flush()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
x
Reference in New Issue
Block a user