kls/kls

141 lines
6.3 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
import curses
import subprocess
stdscr = None
def init_screen():
global stdscr
stdscr = curses.initscr()
stdscr.refresh()
curses.noecho()
curses.cbreak()
stdscr.keypad(True)
curses.curs_set(0)
init_screen()
class Menu:
def __init__(self, name, rows, begin_x):
self.name = name # заголовок окна
self.rows = rows
self.begin_x = begin_x
self.win = curses.newwin(curses.LINES, curses.COLS // 3, 0, begin_x)
self.win.box()
self.win.addstr(1, 2, self.name)
for index, row in enumerate(self.rows):
self.win.addstr(index + 3, 2, row)
self.row = 0
# рисуем первое меню
## готовим контент
bytes_list = subprocess.check_output("kubectl get ns --no-headers -o template='{{range .items}}{{.metadata.name}} {{end}}'", shell=True).split()
namespaces = [bytes_list[i].decode('utf-8') for i in range(len(bytes_list))]
## отрисовываем меню
menu1 = Menu("Namespaces", namespaces, 0)
# рисуем второе меню
## готовим контент
api_resources = ["pods", "services", "deployments", "ingresses"]
## отрисовываем меню
menu2 = Menu("API resources", api_resources, 0 + curses.COLS // 3)
# рисуем третье меню
## готовим контент
bytes_list = subprocess.check_output("kubectl get pods -n kube-system --no-headers -o template='{{range .items}}{{.metadata.name}} {{end}}'", shell=True).split()
pods = [bytes_list[i].decode('utf-8') for i in range(len(bytes_list))]
## отрисовываем меню
menu3 = Menu("Resources", pods, 0 + curses.COLS // 3 * 2)
menus = [menu1, menu2, menu3]
def run_command(command, current_menu, rows=None):
namespace = menus[0].rows[menus[0].row]
api_resource = menus[1].rows[menus[1].row]
resource = menus[2].rows[menus[2].row]
subprocess.call(eval(command), shell=True)
init_screen()
for menu in menus:
menu.win.clear()
menu.win.box()
menu.win.addstr(1, 2, menu.name)
if rows and menu.name == "Resources":
menu.rows = rows
menu.row = 0
for index, row in enumerate(menu.rows):
menu.win.addstr(index + 3, 2, row)
menu.win.addstr(menu.row + 3, 2, menu.rows[menu.row], curses.A_REVERSE | curses.A_ITALIC)
menus[current_menu].win.addstr(1, 2, menus[current_menu].name, curses.A_REVERSE | curses.A_ITALIC)
def navigate_horizontally(direction, current_menu):
increment = {"right": 1, "left": -1}
menus[current_menu].win.addstr(1, 2, menus[current_menu].name) # удаляем выделение с текущего меню
current_menu = (current_menu + increment[direction]) % 3 # переходим к предыдущему/следующему меню
menus[current_menu].win.addstr(1, 2, menus[current_menu].name, curses.A_REVERSE | curses.A_ITALIC) # и выделяем его
return current_menu
def navigate_vertically(direction, current_menu):
increment = {"down": 1, "up": -1}
if current_menu == 2 and menus[2].rows[menus[2].row].startswith("No resources"):
return
menu = menus[current_menu]
menu.win.addstr(menu.row + 3, 2, menu.rows[menu.row]) # удаляем выделение с текущей строки
menu.row = (menu.row + increment[direction]) % len(menu.rows) # переходим к предыдущей/следующей строке
menu.win.addstr(menu.row + 3, 2, menu.rows[menu.row], curses.A_REVERSE | curses.A_ITALIC) # и выделяем её
if current_menu != 2: # если изменился выбор нэймспейса или апи ресурса
namespace = menus[0].rows[menus[0].row]
api_resource = menus[1].rows[menus[1].row]
command = "f'kubectl get {api_resource} -n {namespace} --no-headers -o template=\"{{{{range .items}}}}{{{{.metadata.name}}}} {{{{end}}}}\"'"
bytes_list = subprocess.check_output(eval(command), shell=True).split()
resources = [bytes_list[i].decode('utf-8') for i in range(len(bytes_list))]
if not resources:
resources = [f"No resources found in {namespace} namespace.",]
run_command(command, current_menu, rows=resources)
def main(stdscr):
stdscr.refresh()
running = True
current_menu = 0
menus[current_menu].win.addstr(1, 2, menus[current_menu].name, curses.A_REVERSE | curses.A_ITALIC)
for menu in menus:
menu.win.addstr(3, 2, menu.rows[menu.row], curses.A_REVERSE | curses.A_ITALIC)
while running:
[menu.win.refresh() for menu in menus] # refresh all menus
key_pressed = stdscr.getkey()
match key_pressed:
case 'q':
running = False
case 'g':
if current_menu == 2 and not menus[2].rows[menus[2].row].startswith("No resources"):
run_command("f'kubectl -n {namespace} get {api_resource} {resource} -o yaml | batcat -l yaml --paging always --style numbers'", current_menu)
case 'd':
if current_menu == 2 and not menus[2].rows[menus[2].row].startswith("No resources"):
run_command("f'kubectl -n {namespace} describe {api_resource} {resource} | batcat -l yaml --paging always --style numbers'", current_menu)
case 'l':
if current_menu == 2 and not menus[2].rows[menus[2].row].startswith("No resources") and menus[1].rows[menus[1].row] == "pods":
run_command("f'kubectl -n {namespace} logs {resource} | batcat -l log --paging always --style numbers'", current_menu)
case 'e':
if current_menu == 2 and not menus[2].rows[menus[2].row].startswith("No resources"):
run_command("f'kubectl edit {api_resource} -n {namespace} {resource}'", current_menu)
case '\t' | "KEY_RIGHT":
current_menu = navigate_horizontally("right", current_menu)
case "KEY_BTAB" | "KEY_LEFT":
current_menu = navigate_horizontally("left", current_menu)
case "KEY_DOWN":
navigate_vertically("down", current_menu)
case "KEY_UP":
navigate_vertically("up", current_menu)
main(stdscr)
curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.endwin()
subprocess.call(["clear"])