mirror of
https://gitlab.sectorq.eu/jaydee/portainer.git
synced 2025-12-14 10:44:52 +01:00
build
This commit is contained in:
4
port.py
4
port.py
@@ -27,6 +27,7 @@ class Portainer:
|
||||
def __init__(self, site, timeout=10):
|
||||
self.base_url = None
|
||||
self.token = None
|
||||
self.action = None
|
||||
self._debug = False
|
||||
self.timeout = timeout
|
||||
self.git_url = "git@gitlab.sectorq.eu:home/docker-compose.git"
|
||||
@@ -36,6 +37,7 @@ class Portainer:
|
||||
self.stack_ids = []
|
||||
self.endpoint_name = None
|
||||
self.endpoint_id = None
|
||||
|
||||
# self.git_url = "https://gitlab.sectorq.eu/home/docker-compose.git"
|
||||
self.git_url = "git@gitlab.sectorq.eu:home/docker-compose.git"
|
||||
self.repo_dir = "/tmp/docker-compose"
|
||||
@@ -192,7 +194,7 @@ class Portainer:
|
||||
self.get_containers(self)
|
||||
return True
|
||||
|
||||
def get_stacks(self, endpoint_id="all", timeout=10):
|
||||
def get_stacks(self, endpoint_id="all", timeout=20):
|
||||
'''Get a list of stacks for a specific endpoint or all endpoints.'''
|
||||
if endpoint_id != "all":
|
||||
endpoint_id = self.get_endpoint_id(endpoint_id)
|
||||
|
||||
170
portainer.py
170
portainer.py
@@ -19,7 +19,12 @@ from port import Portainer
|
||||
from prompt_toolkit import prompt
|
||||
from prompt_toolkit.completion import WordCompleter
|
||||
from prompt_toolkit.shortcuts import checkboxlist_dialog
|
||||
|
||||
from prompt_toolkit.shortcuts import radiolist_dialog
|
||||
from prompt_toolkit.application import Application
|
||||
from prompt_toolkit.layout import Layout
|
||||
from prompt_toolkit.widgets import RadioList
|
||||
from prompt_toolkit.key_binding import KeyBindings
|
||||
from prompt_toolkit.layout.containers import HSplit
|
||||
VERSION = "0.1.3"
|
||||
|
||||
defaults = {
|
||||
@@ -32,6 +37,91 @@ defaults = {
|
||||
}
|
||||
|
||||
cur_config = {}
|
||||
|
||||
def menu(title, options):
|
||||
"""
|
||||
Display a menu and return selected value.
|
||||
options must be list of (value, text) or text (auto-wrapped)
|
||||
"""
|
||||
if isinstance(options[0], str):
|
||||
options = [(item, item) for item in options]
|
||||
|
||||
radio = RadioList(options)
|
||||
|
||||
kb = KeyBindings()
|
||||
|
||||
@kb.add("enter")
|
||||
def _(event):
|
||||
event.app.exit(result=radio.current_value)
|
||||
@kb.add("q")
|
||||
def _(event):
|
||||
event.app.exit(result=None)
|
||||
layout = Layout(HSplit([radio]))
|
||||
|
||||
app = Application(
|
||||
layout=layout,
|
||||
key_bindings=kb,
|
||||
full_screen=True
|
||||
)
|
||||
|
||||
return app.run()
|
||||
|
||||
|
||||
# --------------------------
|
||||
# MULTI-LEVEL MENU
|
||||
# --------------------------
|
||||
|
||||
def main_menu():
|
||||
while True:
|
||||
choice = menu("Main Menu", [
|
||||
"System",
|
||||
"Network",
|
||||
"Services",
|
||||
"Exit"
|
||||
])
|
||||
|
||||
if choice == "System":
|
||||
system_menu()
|
||||
|
||||
elif choice == "Network":
|
||||
network_menu()
|
||||
|
||||
elif choice == "Services":
|
||||
services_menu()
|
||||
|
||||
elif choice == "Exit":
|
||||
return
|
||||
|
||||
|
||||
def system_menu():
|
||||
choice = menu("System Menu", [
|
||||
"Info",
|
||||
"Reboot",
|
||||
"Back"
|
||||
])
|
||||
print("SYSTEM →", choice)
|
||||
|
||||
|
||||
def network_menu():
|
||||
choice = menu("Network Menu", [
|
||||
"Show IP",
|
||||
"Restart Networking",
|
||||
"Back"
|
||||
])
|
||||
print("NETWORK →", choice)
|
||||
|
||||
|
||||
def services_menu():
|
||||
choice = menu("Services", [
|
||||
"Start Service",
|
||||
"Stop Service",
|
||||
"Status",
|
||||
"Back"
|
||||
])
|
||||
print("SERVICES →", choice)
|
||||
|
||||
|
||||
|
||||
def load_config(defaults=defaults):
|
||||
'''Load configuration from /myapps/portainer.conf if it exists, else from env vars or defaults.'''
|
||||
if os.path.exists("/myapps/portainer.conf"):
|
||||
@@ -212,7 +302,7 @@ def wl(msg):
|
||||
print(msg)
|
||||
|
||||
|
||||
def prompt_missing_args(args_in, defaults_in, fields, action=None):
|
||||
def prompt_missing_args(args_in, defaults_in, fields, action=None,stacks=None):
|
||||
"""
|
||||
fields = [("arg_name", "Prompt text")]
|
||||
"""
|
||||
@@ -227,6 +317,7 @@ def prompt_missing_args(args_in, defaults_in, fields, action=None):
|
||||
value_in = getattr(args_in, field)
|
||||
default = defaults_in.get(f"PORTAINER_{field}".upper())
|
||||
cur_site = defaults_in.get("PORTAINER_SITE".upper())
|
||||
cur_env = defaults_in.get("PORTAINER_ENVIRONMENT_ID".upper())
|
||||
if value_in is None:
|
||||
if default is not None:
|
||||
prompt_text = f"{text} (default={default}) : "
|
||||
@@ -241,13 +332,19 @@ def prompt_missing_args(args_in, defaults_in, fields, action=None):
|
||||
commands = por.endpoints_names
|
||||
elif field == "stack":
|
||||
if args.action == "create_stack":
|
||||
# input(json.dumps(stacks, indent=2))
|
||||
commands = [
|
||||
'authentik', 'bitwarden', 'bookstack', 'dockermon', 'fail2ban', 'gitea', 'gitlab', 'grafana',
|
||||
'home-assistant', 'homepage', 'immich', 'influxdb', 'jupyter', 'kestra', 'mailu3',
|
||||
'mealie', 'mediacenter', 'mosquitto', 'motioneye', 'n8n', 'nextcloud', 'nginx',
|
||||
'mealie', 'mediacenter', 'mosquitto', 'motioneye', 'n8n', 'nebula', 'nextcloud', 'nginx',
|
||||
'node-red', 'octoprint', 'ollama', 'pihole', 'portainer-ce', 'rancher', 'registry',
|
||||
'regsync', 'semaphore', 'unifibrowser', 'uptime-kuma', 'watchtower', 'wazuh', 'webhub',
|
||||
'wud', 'zabbix-server']
|
||||
for s in por.all_data['stacks'][defaults_in[f"PORTAINER_ENDPOINT_ID".upper()]]['by_name'].keys():
|
||||
|
||||
# print(s)
|
||||
commands.remove(s)
|
||||
|
||||
else:
|
||||
commands = []
|
||||
if por._debug:
|
||||
@@ -280,11 +377,11 @@ def prompt_missing_args(args_in, defaults_in, fields, action=None):
|
||||
).run()
|
||||
if value_in is None:
|
||||
print("Cancelled.")
|
||||
sys.exit(0)
|
||||
elif "__ALL__" in value_in:
|
||||
# User selected "Select ALL"
|
||||
value_in = commands # all real commands
|
||||
if "pihole" in value_in:
|
||||
|
||||
if action == "delete_stack":
|
||||
value_in.remove("pihole")
|
||||
value_in.append("pihole")
|
||||
@@ -333,7 +430,6 @@ def prompt_missing_args(args_in, defaults_in, fields, action=None):
|
||||
|
||||
if field == "site" and value_in != cur_site:
|
||||
por.get_site(value_in)
|
||||
|
||||
if field == "stack" and value_in != cur_site:
|
||||
os.environ[field] = ",".join(value_in)
|
||||
else:
|
||||
@@ -364,35 +460,52 @@ if __name__ == "__main__":
|
||||
os.system("cls" if os.name == "nt" else "clear")
|
||||
if args.action is None:
|
||||
actions = [
|
||||
"create_stack",
|
||||
"delete_stack",
|
||||
"stop_stack",
|
||||
"start_stack",
|
||||
"list_stacks",
|
||||
"update_stack",
|
||||
"secrets",
|
||||
"print_all_data",
|
||||
"list_endpoints",
|
||||
"list_containers",
|
||||
"stop_containers",
|
||||
"start_containers",
|
||||
"refresh_environment",
|
||||
"refresh_status",
|
||||
"update_status",
|
||||
("create_stack","create_stack"),
|
||||
("delete_stack","delete_stack"),
|
||||
("stop_stack","stop_stack"),
|
||||
("start_stack","start_stack"),
|
||||
("list_stacks","list_stacks"),
|
||||
("update_stack","update_stack"),
|
||||
("secrets","secrets"),
|
||||
("print_all_data","print_all_data"),
|
||||
("list_endpoints","list_endpoints"),
|
||||
("list_containers","list_containers"),
|
||||
("stop_containers","stop_containers"),
|
||||
("start_containers","start_containers"),
|
||||
("refresh_environment","refresh_environment"),
|
||||
("refresh_status","refresh_status"),
|
||||
("update_status","update_status"),
|
||||
]
|
||||
print("Possible actions: \n")
|
||||
i = 1
|
||||
for a in actions:
|
||||
print(f" > {i:>2}. {a}")
|
||||
i += 1
|
||||
ans = input("\nSelect action to perform: ")
|
||||
args.action = actions[int(ans) - 1]
|
||||
|
||||
selected_action = radiolist_dialog(
|
||||
title="Select one service",
|
||||
text="Choose a service:",
|
||||
values=actions
|
||||
).run()
|
||||
|
||||
|
||||
|
||||
print("Selected:", selected_action)
|
||||
|
||||
|
||||
|
||||
|
||||
# print("Possible actions: \n")
|
||||
# i = 1
|
||||
# for a in actions:
|
||||
# print(f" > {i:>2}. {a}")
|
||||
# i += 1
|
||||
# ans = input("\nSelect action to perform: ")
|
||||
args.action = selected_action
|
||||
|
||||
|
||||
os.system("cls" if os.name == "nt" else "clear")
|
||||
# Example: list endpoints
|
||||
por = Portainer(cur_config["PORTAINER_SITE"], timeout=args.timeout)
|
||||
por.set_defaults(cur_config)
|
||||
if args.debug:
|
||||
por._debug = True
|
||||
|
||||
if args.action == "secrets":
|
||||
args = prompt_missing_args(
|
||||
args,
|
||||
@@ -402,7 +515,6 @@ if __name__ == "__main__":
|
||||
("endpoint_id", "Endpoint ID"),
|
||||
],
|
||||
)
|
||||
|
||||
secrets = {
|
||||
"gitea_runner_registration_token": "8nmKqJhkvYwltmNfF2o9vs0tzo70ufHSQpVg6ymb",
|
||||
"influxdb2-admin-token": "l4c1j4yd33Du5lo",
|
||||
@@ -437,6 +549,7 @@ if __name__ == "__main__":
|
||||
sys.exit()
|
||||
|
||||
if args.action == "create_stack":
|
||||
por.action = "create_stack"
|
||||
args = prompt_missing_args(
|
||||
args,
|
||||
cur_config,
|
||||
@@ -447,6 +560,7 @@ if __name__ == "__main__":
|
||||
("stack_mode", "Stack mode (swarm or compose)"),
|
||||
("deploy_mode", "Deploy mode (git or upload)"),
|
||||
],
|
||||
por,
|
||||
)
|
||||
por.create_stack(
|
||||
args.endpoint_id,
|
||||
|
||||
Reference in New Issue
Block a user