From 6a7971cd17fb8f3f6696c80e6dccd6bfd608887b Mon Sep 17 00:00:00 2001 From: jblu Date: Mon, 10 Apr 2023 22:51:37 -0500 Subject: [PATCH] #9 #8 #7 lots of changes, performant --- .gitignore | 2 +- cclient.py | 26 +++++++++++------------- cprocess.py | 36 ++++++--------------------------- crane.py | 21 ++++++++++---------- test_crane.py | 55 +++++++++++++++++---------------------------------- 5 files changed, 46 insertions(+), 94 deletions(-) diff --git a/.gitignore b/.gitignore index 073488f..bda7722 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ *.csv *.toml .vscode/ - +thunder-tests/ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/cclient.py b/cclient.py index 22e0bb9..3036b7d 100644 --- a/cclient.py +++ b/cclient.py @@ -1,25 +1,21 @@ -def c_auth(req_obj, host, port, username, password): - url = f'https://{host}:{port}/api/auth' - c_auth_response = req_obj.post(url, json={"Username":username,"Password":password}, verify=False) - return c_auth_response.json()["jwt"] - -def c_get_containers(req_obj, host, port, jwt, endpoint): +def c_get_containers(req_obj, host, port, access_token, endpoint): url = f'https://{host}:{port}/api/endpoints/{endpoint}/docker/containers/json?all=true' - c_get_containers_response = req_obj.get(url, headers={"Authorization": f"Bearer {jwt}"},verify=False) + c_get_containers_response = req_obj.get(url, headers={"X-API-Key": access_token},verify=False) return c_get_containers_response.json() -#filters={"name": ["restic","qbittorrent"],"status": ["paused","dead","created","exited","removing","restarting","created"]} -def c_get_filtered_containers(req_obj, host, port, jwt, endpoint, containers, statuses): - url = f'https://{host}:{port}/api/endpoints/{endpoint}/docker/containers/json?filters={"name": {containers},"status": {statuses}}' - c_get_containers_response = req_obj.get(url, headers={"Authorization": f"Bearer {jwt}"},verify=False) +def c_get_filtered_containers(req_obj, j_obj, host, port, access_token, endpoint, containers, statuses): + filter_string = j_obj.dumps({"name":containers,"status":statuses}) + # url = 'https://192.168.4.11:9443/api/endpoints/1/docker/containers/json?filters={"name": ["restic","qbittorrent"],"status": ["paused","dead","created","exited","removing","restarting","created"]}' + url = f'https://{host}:{port}/api/endpoints/{endpoint}/docker/containers/json?filters={filter_string}' + c_get_containers_response = req_obj.get(url, headers={"X-API-Key": access_token}, verify=False) return c_get_containers_response.json() -def c_start_container(req_obj, host, port, jwt, endpoint, cid): +def c_start_container(req_obj, host, port, access_token, endpoint, cid): url = f'https://{host}:{port}/api/endpoints/{endpoint}/docker/containers/{cid}/start' - c_start_container_response = req_obj.post(url, headers={"Authorization": f"Bearer {jwt}"},verify=False) + c_start_container_response = req_obj.post(url, headers={"X-API-Key": access_token},verify=False) return c_start_container_response.status_code -def c_stop_container(req_obj, host, port, jwt, endpoint, cid): +def c_stop_container(req_obj, host, port, access_token, endpoint, cid): url = f'https://{host}:{port}/api/endpoints/{endpoint}/docker/containers/{cid}/stop' - c_start_container_response = req_obj.post(url, headers={"Authorization": f"Bearer {jwt}"},verify=False) + c_start_container_response = req_obj.post(url, headers={"X-API-Key": access_token},verify=False) return c_start_container_response.status_code \ No newline at end of file diff --git a/cprocess.py b/cprocess.py index 442a075..fff9631 100644 --- a/cprocess.py +++ b/cprocess.py @@ -1,32 +1,8 @@ -# TODO add file for containers that need to be started - -def build_cont_list(obj, hypercare_containers): - cont_list = [] - for i, c in enumerate(obj): - if c["State"].lower() != "running": - continue - if c["Names"][0].lstrip("/") in hypercare_containers: - cont_list.append(c) - return cont_list - -def build_full_cont_list(obj, hypercare_containers): - cont_full_list = [] - for i, c in enumerate(obj): - if c["Names"][0].lstrip("/") in hypercare_containers: - cont_full_list.append(c) - return cont_full_list - -def process_cont_list(full_cont_list, start_cont_fn, req_obj, host, port, jwt, endpoint): +def process_cont_list(full_cont_list, start_cont_fn, req_obj, host, port, access_token, endpoint): if full_cont_list: + #print(full_cont_list) + started = [] for container in full_cont_list: - start_cont_fn(req_obj, host, port, jwt, endpoint, container["Id"]) - return container["Names"][0].lstrip("/") - -def process_cont_status(obj): - if not obj: - return -1 # Can't find the containter - for c in enumerate(obj): - if 'running' in c[1]["State"].lower(): - return 0 - if c[1]["State"] != 'running': - return 1 \ No newline at end of file + start_cont_fn(req_obj, host, port, access_token, endpoint, container["Id"]) + started.append(container["Names"][0].lstrip("/")) + return started \ No newline at end of file diff --git a/crane.py b/crane.py index 6440cb0..0d19aa2 100644 --- a/crane.py +++ b/crane.py @@ -1,4 +1,5 @@ import pushover +import json from cclient import * from clogging import * from cprocess import * @@ -20,12 +21,12 @@ class Crn: # Create the logging and pushover objects self.tl = logging self.po = pushover + self.jn = json #Load settings from config.toml #portainer self.host = self.config["portainer"]["host"] self.port = self.config["portainer"]["port"] - self.username = self.config["portainer"]["username"] - self.password = self.config["portainer"]["password"] + self.access_token = self.config["portainer"]["access_token"] self.endpoint = self.config["portainer"]["endpoint"] self.start_containers = self.config["portainer"]["start_containers"] #logging @@ -37,7 +38,8 @@ class Crn: self.po_key = self.config["pushover"]["po_key"] self.po_token = self.config["pushover"]["po_token"] #containers - self.observed_containers = self.config["containers"].values() + self.observed_containers = list(self.config["containers"].values()) + self.container_statuses = ["paused","dead","created","exited","removing","restarting","created"] cont_log(self) cont_notify(self) @@ -45,16 +47,13 @@ class Crn: #logging in try: - self.tl.debug('Authenticating.') - self.jwt = c_auth(self.cc, self.host, self.port, self.username, self.password) - self.tl.info('Authenticated successfully.') - self.cont_obj = c_get_containers(self.cc, self.host, self.port, self.jwt, self.endpoint) + # c_get_filtered_containers(req_obj, j_obj, host, port, access_token, endpoint, containers, statuses) + self.cont_obj = c_get_filtered_containers(self.cc, self.jn, self.host, self.port, self.access_token, self.endpoint,self.observed_containers,self.container_statuses) + # print(self.cont_obj) self.tl.debug('Collected container data.') - self.cont_list = build_full_cont_list(self.cont_obj, self.observed_containers) - self.tl.debug('Building container list.') - self.process_cont_list_response = process_cont_list(self.cont_list, c_start_container, self.cc, self.host, self.port, self.jwt, self.endpoint) + self.process_cont_list_response = process_cont_list(self.cont_obj, c_start_container, self.cc, self.host, self.port, self.access_token, self.endpoint) if self.process_cont_list_response: - self.tl.warning(f'Started: [{self.process_cont_list_response}]') + self.tl.warning(f'Started: {self.process_cont_list_response}') except requests.exceptions.RequestException as e: self.tl.exception(e) diff --git a/test_crane.py b/test_crane.py index 7824c76..823a760 100644 --- a/test_crane.py +++ b/test_crane.py @@ -1,9 +1,10 @@ import unittest import requests +import json from tomllib import load -from cclient import c_auth, c_get_containers, c_start_container, c_stop_container, c_get_filtered_containers -from cprocess import build_cont_list, process_cont_list, build_full_cont_list, process_cont_status -unittest.TestLoader.sortTestMethodsUsing = None +from cclient import c_get_filtered_containers, c_start_container, c_stop_container, c_get_filtered_containers +from cprocess import process_cont_list +# unittest.TestLoader.sortTestMethodsUsing = None class TestCrane(unittest.TestCase): def setUp(self): @@ -11,54 +12,34 @@ class TestCrane(unittest.TestCase): self.config = load(c) self.host = self.config["portainer"]["host"] self.port = self.config["portainer"]["port"] - self.username = self.config["portainer"]["username"] - self.password = self.config["portainer"]["password"] + self.access_token = "ptr_ufS1nADXmrU3QSN3bvITLMQ7oOH9yo3ECb/QNwtIYJ4=" self.endpoint = self.config["portainer"]["endpoint"] - self.cid = 'aa5b217ca6217fd9d268396039da69ea9e4a5aff381b3dceb71edb5a1f4d429d' + self.cid = 'ef8fee86e02b2b82acbddf6f0da1ff023f60bfe52c0b4087cac29c1686ccbac4' self.req_obj = requests - self.hypercare_containers = ['hello-world'] - #self.status_filters = ["paused","dead","created","exited","removing","restarting","created"] - self.jwt = c_auth(self.req_obj, self.host, self.port, self.username, self.password) - self.cont_obj = c_get_containers(self.req_obj, self.host, self.port, self.jwt, self.endpoint) - #self.cont_obj_f = c_get_filtered_containers(self.req_obj, self.host, self.port, self.jwt, self.endpoint,self.hypercare_containers,self.status_filters) + self.j_obj = json + self.hypercare_containers = ['restic','qbittorrent'] + self.status_filters = ["paused","dead","created","exited","removing","restarting","created"] + self.cont_obj = c_get_filtered_containers(self.req_obj,self.j_obj, self.host, self.port, self.access_token, self.endpoint,self.hypercare_containers,self.status_filters) - def test_c_auth(self): - self.assertTrue(self.jwt, "No JWT returned by cauth.") - - def test_c_get_containers(self): - self.assertTrue(self.cont_obj, "No cont object returned by c_get_containers.") - - def test_c_get_containers_f(self): - self.assertTrue(self.cont_obj_f, "No cont object returned by c_get_containers.") - - def test_a_is_hypercare_container_status(self): - self.cont_full_list = build_full_cont_list(self.cont_obj, self.hypercare_containers) - self.process_cont_status_response = process_cont_status(self.cont_full_list) - if self.process_cont_status_response == 0: - c_stop_container(self.req_obj, self.host, self.port, self.jwt, self.endpoint, self.cid) - - def test_build_cont_list(self): - self.cont_list = build_cont_list(self.cont_obj, self.hypercare_containers) - self.assertTrue(self.cont_list, "No cont_list returned by build_cont_list. Does the test container exist?") + def test_c_get_filtered_containers(self): + self.assertTrue(self.cont_obj, "No cont object returned by c_get_filtered_containers.") def test_c_start_container(self): - self.c_start_container_response = c_start_container(self.req_obj, self.host, self.port, self.jwt, self.endpoint, self.cid) + self.c_start_container_response = c_start_container(self.req_obj, self.host, self.port, self.access_token, self.endpoint, self.cid) # print(self.c_start_container_response) self.assertTrue(self.c_start_container_response, "No c_start_container_resonse returned by c_start_container.") # 204 success 304 already on + def test_c_process_cont_list(self): + self.assertTrue(process_cont_list(self.cont_obj, c_start_container, self.req_obj, self.host, self.port, self.access_token, self.endpoint)) + def test_c_stop_container(self): - self.c_stop_container_response = c_stop_container(self.req_obj, self.host, self.port, self.jwt, self.endpoint, self.cid) + self.c_stop_container_response = c_stop_container(self.req_obj, self.host, self.port, self.access_token, self.endpoint, self.cid) # print(self.c_stop_container_response) self.assertTrue(self.c_stop_container_response, "No c_start_container_resonse returned by c_start_container.") - def test_process_cont_list(self): - self.cont_list = build_cont_list(self.cont_obj, self.hypercare_containers) - self.process_cont_list_response = process_cont_list(self.cont_list, c_start_container, self.req_obj, self.host, self.port, self.jwt, self.endpoint) - self.assertTrue(self.process_cont_list_response, "No c_start_container_resonse returned by c_start_container.") - def test_z_tear_down(self): - c_stop_container(self.req_obj, self.host, self.port, self.jwt, self.endpoint, self.cid) + c_stop_container(self.req_obj, self.host, self.port, self.access_token, self.endpoint, self.cid) if __name__ == '__main__':