diff --git a/port.py b/port.py index 5aac7d7..e837881 100644 --- a/port.py +++ b/port.py @@ -725,9 +725,11 @@ class Portainer: self.get_stack(stack, endpoint_id) else: if stack is not None: - self.stack_ids = [self.get_stack(stack, endpoint_id)["Id"]] + self.stack_ids = [self._resolve_stack_id(stack, endpoint_id)] + # print(self.stack_ids) for stck in self.stack_ids: - path = f"/stacks/{stack}/stop" + path = f"/stacks/{stck}/stop" + # print(path) if self.endpoint_id is not None: path += f"?endpointId={self.endpoint_id}" try: diff --git a/portainer.py b/portainer.py index 6ee7623..1b134a1 100755 --- a/portainer.py +++ b/portainer.py @@ -11,6 +11,8 @@ import logging import sys import json import argparse +import tty +import termios from tabulate import tabulate from port import Portainer @@ -189,6 +191,41 @@ def prompt_missing_args(args_in, defaults_in, fields): """ fields = [("arg_name", "Prompt text")] """ + def input_with_default(prompt, default): + full_prompt = f" >> {prompt:40}" + sys.stdout.write(full_prompt) + sys.stdout.flush() + checkmark = "\033[92m\u2714\033[0m" + # read raw input char-by-char + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(fd) + user_input = "" + while True: + ch = sys.stdin.read(1) + if ch in ("\n", "\r"): # ENTER + break + elif ch == "\x7f": # BACKSPACE + if user_input: + user_input = user_input[:-1] + sys.stdout.write("\b \b") + sys.stdout.flush() + else: + user_input += ch + sys.stdout.write(ch) + sys.stdout.flush() + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + + if not user_input: + user_input = default + + # rewrite final line cleanly + sys.stdout.write(f"\r{full_prompt}{user_input:10} {checkmark}\n") + sys.stdout.flush() + + return user_input for field, text in fields: value_in = getattr(args_in, field) default = defaults_in.get(f"PORTAINER_{field}".upper()) @@ -196,10 +233,12 @@ def prompt_missing_args(args_in, defaults_in, fields): if value_in is None: if default is not None: prompt = f"{text} (default={default}) : " - value_in = input(prompt) or default + # value_in = input(prompt) or default + value_in = input_with_default(prompt, default) defaults_in[f"PORTAINER_{field}".upper()] = value_in else: - value_in = input(f"{text}: ") + #value_in = input(f"{text}: ") + value_in = input_with_default(text, default) defaults_in[f"PORTAINER_{field}".upper()] = value_in setattr(args, field, value_in) os.environ[field] = value_in @@ -214,6 +253,7 @@ print(cur_config) if __name__ == "__main__": # Example usage: set PORTAINER_USER and PORTAINER_PASS in env, or pass literals below. # token = get_portainer_token(base,"admin","l4c1j4yd33Du5lo") # or get_portainer_token(base, "admin", "secret") + os.system("cls" if os.name == "nt" else "clear") if args.action is None: actions = [ "create_stack", @@ -232,14 +272,14 @@ if __name__ == "__main__": "refresh_status", "update_status", ] - print("Possible actions: ") + print("Possible actions: \n") i = 1 for a in actions: - print(f" > {i}. {a}") + print(f" > {i:>2}. {a}") i += 1 ans = input("\nSelect action to perform: ") args.action = actions[int(ans) - 1] - + os.system("cls" if os.name == "nt" else "clear") # Example: list endpoints por = Portainer(base, PORTAINER_API_KEY, timeout=args.timeout) @@ -297,18 +337,29 @@ if __name__ == "__main__": sys.exit() if args.action == "stop_stack": - if args.endpoint_id is None: - args.endpoint_id = input("Endpoint ID is required for stopping stacks : ") - if args.stack is None: - args.stack = input("Stack name or ID is required for stopping stacks : ") + args = prompt_missing_args( + args, + cur_config, + [ + ("site", "Site"), + ("endpoint_id", "Endpoint ID"), + ("stack", "Stack name or ID"), + ], + ) + por.stop_stack(args.stack, args.endpoint_id) sys.exit() if args.action == "start_stack": - if args.endpoint_id is None: - args.endpoint_id = input("Endpoint ID is required for starting stacks : ") - if args.stack is None: - args.stack = input("Stack name or ID is required for starting stacks : ") + args = prompt_missing_args( + args, + cur_config, + [ + ("site", "Site"), + ("endpoint_id", "Endpoint ID"), + ("stack", "Stack name or ID"), + ], + ) por.start_stack(args.stack, args.endpoint_id) sys.exit()