import configparser import json import pandas as pd import paramiko import os from tabulate import tabulate class Cluster: def __init__(self, config_path: str, abs_path: str, use_key=False) -> None: self.abs_path = abs_path self.config = configparser.ConfigParser() self.config.read(config_path) self.auth_data = dict(self.config.items("CLUSTER")) self.ssh = paramiko.SSHClient() self.use_key = use_key def connect(self) -> None: self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) if self.use_key: k = paramiko.RSAKey.from_private_key_file( os.path.join(self.abs_path, self.auth_data["key"]) ) self.ssh.connect( hostname=self.auth_data["host"], username=self.auth_data["user"], pkey=k, port=self.auth_data["port"], ) else: self.ssh.connect( hostname=self.auth_data["host"], username=self.auth_data["user"], password=self.auth_data["password"], port=self.auth_data["port"], ) def get_state(self) -> list: self.connect() get_state = "docker node ls" try: ssh_stdin, ssh_stdout, ssh_stderr = self.ssh.exec_command(get_state) except Exception as e: print(ssh_stderr) print(e) return 1 ssh_stdout.channel.set_combine_stderr(True) output = ssh_stdout.readlines() self.ssh.close() return output def run_ansible_command(self, command: str, use_configs=False) -> list: self.connect() if use_configs: command = "cd devops-configs/ansible && " + command print(command) try: ssh_stdin, ssh_stdout, ssh_stderr = self.ssh.exec_command(command) ssh_stdout.channel.set_combine_stderr(True) output = ssh_stdout.readlines() except Exception as e: print(ssh_stderr) print(e) output = ssh_stderr.readlines() self.ssh.close() # formatted_output = "".join(output) # return json.loads(formatted_output) return output def format_state(self, as_json=False) -> str: state = self.get_state() keys = state[0].split() f_state = [] try: for node in state[1:-1]: buffer = {} line = node.split() for i, j in zip(line, keys): buffer.update({j: i}) f_state.append(buffer) df = pd.DataFrame(f_state) df = df.rename(columns={"MANAGER": "ENGINE"}) df["MANAGER"] = "" leader = state[-1].split() df2 = pd.DataFrame( { "ID": leader[0], "HOSTNAME": leader[2], "STATUS": leader[3], "AVAILABILITY": leader[4], "ENGINE": leader[6], "MANAGER": leader[5], }, index=[0], ) df = pd.concat([df, df2], ignore_index=True) print(tabulate(df, headers="keys", tablefmt="psql")) if not as_json: return df.to_json(orient="records") else: # return tabulate(df, headers="keys", tablefmt="psql") return df.to_dict("records") except Exception as e: print(e) return "Format failed" if __name__ == "__main__": cluster = Cluster( os.path.join(os.path.dirname(os.path.realpath(__file__)), "config.ini"), os.path.dirname(os.path.realpath(__file__)), ) print(cluster.format_state())