From 101bfbc9a422d9d3337833ff9fcfc2d3a0b019db Mon Sep 17 00:00:00 2001 From: jaydee Date: Thu, 11 Dec 2025 22:10:12 +0100 Subject: [PATCH] build --- port.py | 84 ++++++++++++++++++++++++++++++++++++++++++++-------- portainer.py | 21 ++++++++++++- 2 files changed, 91 insertions(+), 14 deletions(-) diff --git a/port.py b/port.py index 2ceac88..60a1992 100644 --- a/port.py +++ b/port.py @@ -109,12 +109,13 @@ class Portainer: ] self.log_mode = False self.hw_mode = False - self.all_data = {"containers": {}, "stacks": {}, "endpoints": {}} + self.all_data = {"containers": {}, "stacks": {}, "endpoints": {}, "services":{}} self.get_site(site) self.get_endpoints() self.get_stacks() self.get_containers() + def set_defaults(self, config): '''Set default configuration from provided config dictionary.''' self.cur_config = config @@ -272,9 +273,11 @@ class Portainer: # input(json.dumps(self.stacks_all,indent=2)) return stcks - def get_services(self, endpoint, stack, timeout=30): + def get_services(self, endpoint, timeout=30): '''Get a list of services for a specific stack on an endpoint.''' - path = f"/endpoints/{self.all_data['endpoints']['by_name'][endpoint]}/docker/services" + print(json.dumps(self.all_data,indent=2)) + path = f"/endpoints/{endpoint}/docker/services" + print(path) #path += f'?filters={{"label": ["com.docker.compose.project={stack}"]}}' services = self._api_get(path, timeout=timeout) return services @@ -756,6 +759,70 @@ class Portainer: print(f"Total stacks: {count}") # print(sorted(stack_names)) + def update_service(self, endpoint_id=None, service_id=None): + all_services = self.get_services(self.get_endpoint_id(endpoint_id)) + + service_tuples = [(s['ID'], s['Spec']['Name']) for s in all_services] + + input(service_tuples) + if service_id == "all": + + service_id = self.all + #services = [(s["Id"], s["Name"]) for s in self.get_stacks(endpoint_id)] + services.insert(0, ("__ALL__", "[Select ALL]")) + service_ids = checkboxlist_dialog( + title="Select one service", + text="Choose a service:", + values=services + ).run() + if service_ids == "__ALL__": + pass + print(service_ids) + service_dict = dict(service_ids) + services = self.get_services(self.endpoint_name, stack_id) + svc_name = service_dict.get(stack_id) + stack_svcs = [] + svc_menu = [] + for s in services: + try: + if svc_name in s['Spec']['Name']: + stack_svcs.append([s['Version']['Index'], s['Spec']['Name']]) + svc_menu.append([s['ID'], s['Spec']['Name']]) + except KeyError as e: + print(e) + + + service_id = radiolist_dialog( + title="Select one service", + text="Choose a service:", + values=svc_menu + ).run() + + + """Restart a service on an endpoint.""" + path = f"/docker/{self.endpoint_id}/services/{service_id}/image_status?refresh=true" + + try: + resp = self._api_get(path, timeout=20) + except ValueError as e: + print(f"Error restarting service: {e}") + return [] + if resp['Status'] == "outdated": + self.restart_srv(service_id, True) + print(f"Service {service_id} : restarted") + return True + + def restart_srv(self,service_id, pool=False): + """Restart a service on an endpoint.""" + path = f"/endpoints/{self.endpoint_id}/forceupdateservice" + params={"serviceID": service_id, "pullImage": pool} + try: + resp = self._api_put(path, json=params, timeout=20) + print(resp) + except ValueError as e: + print(f"Error restarting service: {e}") + return [] + def restart_service(self, endpoint_id, service_id): stacks = [(s["Id"], s["Name"]) for s in self.get_stacks(endpoint_id)] stack_id = radiolist_dialog( @@ -782,17 +849,8 @@ class Portainer: text="Choose a service:", values=svc_menu ).run() - - """Restart a service on an endpoint.""" - path = f"/endpoints/{self.endpoint_id}/forceupdateservice" - params={"serviceID": service_id, "pullImage": False} - try: - resp = self._api_put(path, json=params, timeout=20) - print(resp) - except ValueError as e: - print(f"Error restarting service: {e}") - return [] + self.restart_srv(service_id, False) print(f"Service {service_id} : restarted") return True diff --git a/portainer.py b/portainer.py index abb946b..f8f906a 100755 --- a/portainer.py +++ b/portainer.py @@ -109,6 +109,13 @@ parser.add_argument( default=None, help="Endpoint ID to limit stack operations", ) +parser.add_argument( + "--service-id", + "-i", + type=str, + default=None, + help="Service ID to limit service operations", +) parser.add_argument( "--refresh-environment", "-R", action="store_true", help="List endpoints" ) @@ -393,6 +400,7 @@ if __name__ == "__main__": ("stop_stack","stop_stack"), ("start_stack","start_stack"), ("restart_service","restart_service"), + ("update_service","update_service"), ("list_stacks","list_stacks"), ("update_stack","update_stack"), ("secrets","secrets"), @@ -538,7 +546,18 @@ if __name__ == "__main__": ) por.restart_service(args.endpoint_id, "lala") sys.exit() - + + if args.action == "update_service": + args = prompt_missing_args( + args, + cur_config, + [ + ("site", "Site"), + ("endpoint_id", "Endpoint ID") + ], + ) + por.update_service(args.endpoint_id, args.service_id) + sys.exit() if args.action == "list_stacks": args = prompt_missing_args( args,