diff --git a/colout/colout.py b/colout/colout.py index 8c64d68..6a02b23 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -41,7 +41,7 @@ context["styles"] = { "reverse": 7, "conceal": 8 } -error_codes = {"UnknownColor": 1, "DuplicatedPalette": 2, "MixedModes": 3, "UnknownLexer": 4} +error_codes = {"UnknownColor": 1, "DuplicatedPalette": 2, "MixedModes": 3, "UnknownLexer": 4, "CustomSelectorError": 5} # Available color names in 8-colors mode. eight_colors = ["black","red","green","yellow","blue","magenta","cyan","white"] @@ -110,6 +110,81 @@ class DuplicatedTheme(Exception): class MixedModes(Exception): pass +class CustomSelectorError(Exception): + pass + +############################################################################### +# Custom selectors for coloring +############################################################################### +class BaseSelector: + """ + Base class for custom selectors. Should have color() and split() methods + """ + def split(self, sep): + """ + Just emulate string.split() + """ + return [self] + + def color(self, text): + """ + Override this method in custom classes + """ + return "none" + +class PercentSelector(BaseSelector): + """ + Allow to compare two numbers and select colors by percents range. + Numbers will be obtained as group(1) and group(2): + percents = int(group(1)*100/group(2)) + If only one group is used - group(1) will be using as percents + """ + + def __init__(self, regex, groups=2, ranges=(30,80), colors=("red", "yellow", "green") ): + """ + groups - groups number. Allowed values is 1 or 2 (compare two digits) + range - color ranges in percents + colors - colors for each range + E.g. + range=(30,80) and color=("red", "yellow", "green") + <=30% - red color + 30-80% - yellow color + >=80% - green color + """ + if groups not in (1,2): + raise CustomSelectorError("PercentSelector: only 1 or 2 is possible as groups counter") + if len(ranges) + 1 != len(colors): + raise CustomSelectorError("PercentSelector: len(colors) should be equal to len(ranges)+1") + self.regex = re.compile(regex) + self.groups = groups + self.ranges = ranges + self.colors = colors + + def color(self, text): + match = self.regex.match(text) + # What we should do if regex is not matching? + if match is not None: + if self.groups == 2: + number1 = int(match.group(1)) + number2 = int(match.group(2)) + percent = number1*100/number2 + else: + percent = int(match.group(1)) + + cnt=0 + for r in self.ranges: + if percent <= r: + return self.colors[cnt] + else: + cnt+=1 + return self.colors[-1] + raise CustomSelectorError("PercentSelector: regex does not matched") + +context['Selectors'] = { + 'base': BaseSelector, + 'percent': PercentSelector, +} + ############################################################################### # Ressource parsing helpers @@ -651,6 +726,9 @@ def colorout(text, match, prev_end, color="red", style="normal", group=0): colored_text = text[prev_end:start] end = match.end(group) + if isinstance(color, BaseSelector): + color = color.color(match.group(group)) + colored_text += colorin(text[start:end], color, style) return colored_text, end @@ -1089,6 +1167,9 @@ def main(): + " Check the following 'color:mode' pairs: %s." % e ) sys.exit( error_codes["MixedModes"] ) + except CustomSelectorError as e: + logging.error("Error occured in custom selector: %s" % e) + sys.exit( error_codes["CustomSelectorError"] ) if __name__ == "__main__": main() diff --git a/colout/colout_kubectlnodes.py b/colout/colout_kubectlnodes.py new file mode 100644 index 0000000..bcb31af --- /dev/null +++ b/colout/colout_kubectlnodes.py @@ -0,0 +1,13 @@ + +def theme(context): + + return context, [ + ["(NAME|STATUS|ROLES|AGE|VERSION|INTERNAL-IP|EXTERNAL-IP|OS-IMAGE|KERNEL-VERSION|CONTAINER-RUNTIME)", + "white", "underline"], + ["^([^\s]+)", "blue"], + ["(Ready)", "green"], + ["(MemoryPressure|DiskPressure|PIDPressure|NetworkUnavailable|SchedulingDisabled)", "red"], + ["^[^\s]+\s+[^\s]+\s+([^\s]+)", "yellow"], + ["^[^\s]+\s+[^\s]+\s+([^\s]+)\s+([1-9]\d*)\s+", "red"], + ] + diff --git a/colout/colout_kubectlpods.py b/colout/colout_kubectlpods.py new file mode 100644 index 0000000..daa9047 --- /dev/null +++ b/colout/colout_kubectlpods.py @@ -0,0 +1,17 @@ +#encoding: utf-8 + +def theme(context): + + return context, [ + ["(NAME|READY|STATUS|RESTARTS|AGE|IP|NODE|NOMINATED|NODE|READINESS|GATES)", + "white", "underline"], + ["^([^\s]+)", "blue"], + ["(\d+/\d+)", + context['Selectors']['percent'](r'(\d+)/(\d+)', groups=2, ranges=(30,80), colors=("red", "yellow", "green")) + ], + ["(Running)", "green"], + ["(CrashLoopBackOff|RunContainerError|Error)", "red"], + ["^[^\s]+\s+[^\s]+\s+([^\s]+)", "yellow"], + ["^[^\s]+\s+[^\s]+\s+([^\s]+)\s+([1-9]\d*)\s+", "red"], + ] +