diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e253fb0..e9de1ed3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [2.30.4] - 2024-10-15 +### Added +#### BOS option +- cfs_read_timeout: Allow the amount of time BOS waits for a response from CFS before + timing out to be configurable ## [2.30.3] - 2024-10-10 ### Changed diff --git a/api/openapi.yaml.in b/api/openapi.yaml.in index 9cb652be..31475590 100644 --- a/api/openapi.yaml.in +++ b/api/openapi.yaml.in @@ -976,6 +976,13 @@ components: Options for the Boot Orchestration Service. type: object properties: + cfs_read_timeout: + type: integer + description: | + The amount of time (in seconds) to wait for a response before timing out a request to CFS + example: 20 + minimum: 10 + maximum: 86400 cleanup_completed_session_ttl: type: string description: | diff --git a/src/bos/common/options.py b/src/bos/common/options.py index d876e50a..f01914c6 100644 --- a/src/bos/common/options.py +++ b/src/bos/common/options.py @@ -29,6 +29,7 @@ # code should either import this dict directly, or (preferably) access # its values indirectly using a DefaultOptions object DEFAULTS = { + 'cfs_read_timeout': 20, 'cleanup_completed_session_ttl': "7d", 'clear_stage': False, 'component_actual_state_ttl': "4h", @@ -62,6 +63,10 @@ def get_option(self, key: str) -> Any: # All these do is convert the response to the appropriate type for the option, # and return it. + @property + def cfs_read_timeout(self) -> int: + return int(self.get_option('cfs_read_timeout')) + @property def cleanup_completed_session_ttl(self) -> str: return str(self.get_option('cleanup_completed_session_ttl')) diff --git a/src/bos/operators/utils/clients/cfs.py b/src/bos/operators/utils/clients/cfs.py index 6c532b5a..5ac48265 100644 --- a/src/bos/operators/utils/clients/cfs.py +++ b/src/bos/operators/utils/clients/cfs.py @@ -23,6 +23,7 @@ # from collections import defaultdict import logging +from bos.operators.utils.clients.bos.options import options from requests.exceptions import HTTPError from bos.common.utils import compact_response_text, exc_type_msg, requests_retry_session, PROTOCOL @@ -45,7 +46,7 @@ def get_components(session=None, **params): Returns the list of CFS components """ if not session: - session = requests_retry_session() + session = requests_retry_session(read_timeout=options.cfs_read_timeout) # pylint: disable=redundant-keyword-arg component_list = [] while params is not None: LOGGER.debug("GET %s with params=%s", COMPONENTS_ENDPOINT, params) @@ -71,7 +72,7 @@ def patch_components(data, session=None): LOGGER.warning("patch_components called without data; returning without action.") return if not session: - session = requests_retry_session() + session = requests_retry_session(read_timeout=options.cfs_read_timeout) # pylint: disable=redundant-keyword-arg LOGGER.debug("PATCH %s with body=%s", COMPONENTS_ENDPOINT, data) response = session.patch(COMPONENTS_ENDPOINT, json=data) LOGGER.debug("Response status code=%d, reason=%s, body=%s", response.status_code, @@ -88,7 +89,7 @@ def get_components_from_id_list(id_list): LOGGER.warning("get_components_from_id_list called without IDs; returning without action.") return [] LOGGER.debug("get_components_from_id_list called with %d IDs", len(id_list)) - session = requests_retry_session() + session = requests_retry_session(read_timeout=options.cfs_read_timeout) # pylint: disable=redundant-keyword-arg component_list = [] while id_list: next_batch = id_list[:GET_BATCH_SIZE] @@ -106,7 +107,7 @@ def patch_desired_config(node_ids, desired_config, enabled=False, tags=None, cle return LOGGER.debug("patch_desired_config called on %d IDs with desired_config=%s enabled=%s tags=%s" " clear_state=%s", len(node_ids), desired_config, enabled, tags, clear_state) - session = requests_retry_session() + session = requests_retry_session(read_timeout=options.cfs_read_timeout) # pylint: disable=redundant-keyword-arg node_patch = { 'enabled': enabled, 'desired_config': desired_config,