From 83e6f1757537700d04485efdcc41db9cb4a69375 Mon Sep 17 00:00:00 2001 From: tylen Date: Tue, 4 Mar 2025 21:35:16 +0000 Subject: [PATCH] cli: add api client class --- services/tools/cli/api.py | 65 ++++++++++++++++++++++++++++ services/tools/cli/portainer_host.py | 28 ++++++------ 2 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 services/tools/cli/api.py diff --git a/services/tools/cli/api.py b/services/tools/cli/api.py new file mode 100644 index 0000000..31d8e7f --- /dev/null +++ b/services/tools/cli/api.py @@ -0,0 +1,65 @@ +import requests + +class ApiClient(): + def __init__(self, api_url, default_token=None): + super().__init__() + self.api_url = api_url + self.default_token = default_token + + def __request(self, endpoint, payload=None, params=None, method='GET', token=None): + if payload is None: + payload = {} + if params is None: + params = {} + + request_url = f'{self.api_url}{endpoint}' + + headers = {} + if token is None: + token = self.default_token + if token: + headers['Authorization'] = f'Bearer {token}' + + try: + if method.upper() == 'POST': + response = requests.post(request_url, json=payload, headers=headers) + elif method.upper() == 'GET': + response = requests.get(request_url, params=params, headers=headers) + elif method.upper() == 'PUT': + response = requests.put(request_url, json=payload, headers=headers) + elif method.upper() == 'DELETE': + response = requests.delete(request_url, json=payload, headers=headers) + else: + raise ValueError("Unsupported HTTP method: {}".format(method)) + + if response.status_code != 200: + self.warning(f'Return code {response.status_code} from {endpoint} with message {response.text}') + + except requests.exceptions.RequestException as e: + self.error("An error occurred:", e) + return None + + return response + + def get(self, endpoint, params=None, token=None): + return self.__request(endpoint, method='GET', params=params, token=token) + + def post(self, endpoint, payload=None, token=None): + return self.__request(endpoint, payload=payload, method='POST', token=token) + + def put(self, endpoint, payload=None, token=None): + return self.__request(endpoint, payload=payload, method='PUT', token=token) + + def delete(self, endpoint, payload=None, token=None): + return self.__request(endpoint, payload=payload, method='DELETE', token=token) + + def reassign_token(self, token): + self.default_token = token + + def warning(self, message): + print(f"WARNING: {message}") + + def error(self, message, exception=None): + print(f"ERROR: {message}") + if exception: + print(f"Exception: {exception}") diff --git a/services/tools/cli/portainer_host.py b/services/tools/cli/portainer_host.py index 00771b0..6962028 100644 --- a/services/tools/cli/portainer_host.py +++ b/services/tools/cli/portainer_host.py @@ -1,4 +1,5 @@ import json +from api import ApiClient from base import BaseCLi from constants import ( DEFAULT_PORTAINER_JWT_CONFIG_FILE, @@ -19,7 +20,8 @@ class PortainerHost(BaseCLi): def __init__(self, host_url): super().__init__() self.host_url = host_url - self.api_url = f'{host_url}/api' + api_url = f'{host_url}/api' + self.api = ApiClient(api_url=api_url) self.jwt_config = {} self.jwt_token = '' home_directory = os.path.expanduser("~") @@ -44,10 +46,11 @@ class PortainerHost(BaseCLi): raise EmptyConfigException() def __create_config(self, file_path): - self.jwt_token = self.__get_jwt_token() + jwt_token = self.__get_jwt_token() self.jwt_config[self.host_url] = { - "jwt": self.jwt_token, + "jwt": jwt_token, } + self.api.reassign_token(jwt_token) with open(file_path, 'w') as file: json.dump(self.jwt_config, file, indent=4) @@ -62,17 +65,14 @@ class PortainerHost(BaseCLi): "Username": get_env(FUNCTIONAL_USER_USERNAME_ENV), "Password": get_env(FUNCTIONAL_USER_PASSWORD_ENV) } - auth_endpoint = f'{self.api_url}/auth' + + response = self.api.post('/auth', payload=payload) try: - response = requests.post( - auth_endpoint, - json=payload - ) - if response.status_code != 200: - self.error(f'Return code {response.status_code} from {auth_endpoint} with message {response.text}') - except requests.exceptions.RequestException as e: - self.error("An error occurred:", e) - data = response.json() - return data['jwt'] + token = response.json()['jwt'] + except KeyError: + self.error('No "jwt" key in /auth response found.') + return token + +