From 1b4960248f5129c47e3d5e647c5c02404b6d4dd7 Mon Sep 17 00:00:00 2001 From: Carlos Date: Thu, 10 Oct 2024 12:58:00 +0200 Subject: [PATCH] Add timeout to HTTP calls to prevent application hangs. --- Makefile | 46 +++++++++++-------- .../errst2lib/stackstorm_api.py | 37 +++++++++++++-- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 2ca2636..02f372f 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,19 @@ SOURCE_PATH=src/err-stackstorm LIB_PATH=${SOURCE_PATH}/errst2lib TESTS_PATH=tests +# ANSI colour formats for help output. +FMT_TITLE=\e[34;40;1m +FMT_TARGET=\e[37;0;1m +FMT_NONE=\e[0m + .PHONY: all -all: auto_format lint_test unit_test security_scan +all: auto_format format_test lint_test unit_test security_scan -.PHONY: clean +.PHONY: clean # Remove tmp files and previous build artifacst. (Not Implemented) clean: @echo Cleaning - N/A -.PHONY: setup +.PHONY: setup # Install errbot and dependencies into virtual environment. setup: test -n "${CI}" || ( test -n "${VIRTUAL_ENV}" || (echo "Not running in virtualenv/CI - abort setup"; exit 1 ) ) && echo "Running in virtual environment or CI pipeline" pip install --upgrade pip @@ -21,53 +26,56 @@ setup: pip install -r requirements-test.txt pip install -r requirements-build.txt -.PHONY: build_python_package +.PHONY: build_python_package # Build python deployment packages. build_python_package: echo "Build python package" python -m build -.PHONY: publish_pypi +.PHONY: publish_pypi # Push python deployment packages to pypi. (Not Implemented) publish_pypi: echo "Publish python packages to pypi" echo TO DO: python -m twine upload err-stackstorm dist/* -.PHONY: documentation +.PHONY: documentation # Generate readthedocs documentation. (Not Implemented) documentation: echo "Build documentation" echo TO DO - trigger readthedocs. -.PHONY: format_test +.PHONY: format_test # Run black formatting check over source files. format_test: echo "Formatting code\n" black --check --line-length=${MAX_LINE_LEN} ${SOURCE_PATH}/st2.py ${LIB_PATH}/*.py ${TESTS_PATH}/*.py -.PHONY: auto_format +.PHONY: auto_format # Apply black format against python source files. auto_format: echo "Formatting code\n" black --line-length=${MAX_LINE_LEN} ${SOURCE_PATH}/st2.py ${LIB_PATH}/*.py ${TESTS_PATH}/*.py -.PHONY: security_scan +.PHONY: security_scan # Check python source code for security issues. security_scan: echo "Scanning for potential security issues\n" bandit ${SOURCE_PATH}/*.py ${LIB_PATH}/*.py -.PHONY: unit_test +.PHONY: unit_test # Run Unit tests using pytest. unit_test: echo "Running Python unit tests\n" python -m pytest -.PHONY: lint_test +.PHONY: lint_test # Run flake and pycodestyle tests on source files. lint_test: echo -n "Running LINT tests\n" pycodestyle --max-line-length=${MAX_LINE_LEN} ${SOURCE_PATH}/st2.py ${LIB_PATH}/*.py .PHONY: help help: - echo "lint_test: Run flake and pycodestyle tests on source files." - echo "unit_test: Run pytest." - echo "format_test: Run black formatting check over source files." - echo "auto_format: Apply black formatting over source files." - echo "setup: Install errbot and dependencies into virtual environment." - echo "build_python_package: Build a python package of err-stackstorm." - echo "publish_pypi: Upload python package in dist/ to pypi." - echo "documentation: Trigger build on the readthedocs site." + echo "${FMT_TITLE}TARGET${FMT_NONE} ${FMT_TITLE}DESCRIPTION${FMT_NONE}" + echo "${FMT_TARGET}clean${FMT_NONE} Remove tmp files and previous build artifacst. (Not Implemented)" + echo "${FMT_TARGET}setup${FMT_NONE} Install errbot and dependencies into virtual environment." + echo "${FMT_TARGET}build_python_package${FMT_NONE} Build python deployment packages." + echo "${FMT_TARGET}publish_pypi${FMT_NONE} Push python deployment packages to pypi. (Not Implemented)" + echo "${FMT_TARGET}documentation${FMT_NONE} Generate readthedocs documentation. (Not Implemented)" + echo "${FMT_TARGET}format_test${FMT_NONE} Run black formatting check over source files." + echo "${FMT_TARGET}auto_format${FMT_NONE} Apply black format against python source files." + echo "${FMT_TARGET}security_scan${FMT_NONE} Check python source code for security issues." + echo "${FMT_TARGET}unit_test${FMT_NONE} Run Unit tests using pytest." + echo "${FMT_TARGET}lint_test${FMT_NONE} Run flake and pycodestyle tests on source files." diff --git a/src/err-stackstorm/errst2lib/stackstorm_api.py b/src/err-stackstorm/errst2lib/stackstorm_api.py index 1245291..c7ddcaa 100644 --- a/src/err-stackstorm/errst2lib/stackstorm_api.py +++ b/src/err-stackstorm/errst2lib/stackstorm_api.py @@ -29,6 +29,7 @@ def error(self, return_code, message): class StackStormAPI(object): stream_backoff = 10 authenticate_backoff = 10 + http_timeout = 10 def __init__(self, cfg, accessctl): self.cfg = cfg @@ -55,7 +56,13 @@ def enquiry_list(self, st2_creds=None): url = f"{self.cfg.api_url}/inquiries/" params = {} headers = st2_creds.requests() - return requests.get(url, headers=headers, params=params, verify=self.cfg.verify_cert) + return requests.get( + url, + headers=headers, + params=params, + timeout=StackStormAPI.http_timeout, + verify=self.cfg.verify_cert, + ) def enquiry_get(self, enquiry_id, st2_creds=None): """ @@ -100,7 +107,13 @@ def enquiry_get(self, enquiry_id, st2_creds=None): url = f"{self.cfg.api_url}/inquiries/{enquiry_id}" params = {} headers = st2_creds.requests() - response = requests.get(url, headers=headers, params=params, verify=self.cfg.verify_cert) + response = requests.get( + url, + headers=headers, + params=params, + timeout=StackStormAPI.http_timeout, + verify=self.cfg.verify_cert, + ) if response.status_code == requests.codes.ok: return response.json() @@ -132,7 +145,13 @@ def actionalias_help(self, pack=None, filter=None, limit=None, offset=None, st2_ params["offset"] = offset headers = st2_creds.requests() - response = requests.get(url, headers=headers, params=params, verify=self.cfg.verify_cert) + response = requests.get( + url, + headers=headers, + params=params, + timeout=StackStormAPI.http_timeout, + verify=self.cfg.verify_cert, + ) if response.status_code == requests.codes.ok: return response.json().get("helpstrings", []) elif response.status_code == 401: @@ -150,7 +169,11 @@ def match(self, text, st2token): result = Result() try: response = requests.post( - url, headers=headers, data=payload, verify=self.cfg.verify_cert + url, + headers=headers, + data=payload, + timeout=StackStormAPI.http_timeout, + verify=self.cfg.verify_cert, ) if response.status_code == 200: result.OK(response.json()) @@ -195,7 +218,11 @@ def execute_actionalias(self, msg, chat_user, st2token): msg = "" try: response = requests.post( - url, headers=headers, json=payload, verify=self.cfg.verify_cert + url, + headers=headers, + json=payload, + timeout=StackStormAPI.http_timeout, + verify=self.cfg.verify_cert, ) if response.status_code in [201, 400]: