def wait_for_condition( condition: Condition, timeout: int = None, interval: Union[int, float] = 1, fail_on_api_error: bool = True, ) -> None: """Wait for a condition to be met. Args: condition: The Condition to wait for. timeout: The maximum time to wait, in seconds, for the condition to be met. If unspecified, this function will wait indefinitely. If specified and the timeout is met or exceeded, a TimeoutError will be raised. interval: The time, in seconds, to wait before re-checking the condition. fail_on_api_error: Fail the condition checks if a Kubernetes API error is incurred. An API error can be raised for a number of reasons, including a Pod being restarted and temporarily unavailable. Disabling this will cause those errors to be ignored, allowing the check to continue until timeout or resolution. (default: True). Raises: TimeoutError: The specified timeout was exceeded. """ log.info(f"waiting for condition: {condition}") # define the maximum time to wait. once this is met, we should # stop waiting. max_time = None if timeout is not None: max_time = time.time() + timeout # start the wait block start = time.time() while True: if max_time and time.time() >= max_time: raise TimeoutError( f"timed out ({timeout}s) while waiting for condition {condition}" ) # check if the condition is met and break out if it is try: if condition.check(): break except ApiException as e: log.warning(f"got api exception while waiting: {e}") if fail_on_api_error: raise # if the condition is not met, sleep for the interval # to re-check later time.sleep(interval) end = time.time() log.info(f"wait completed (total={end-start}s) {condition}")
def test_condition_check_false(fn, args, kwargs): """Test checking when the function returns Falsey values.""" c = Condition("test", fn, *args, **kwargs) assert not c.check()
def test_condition_check_true(fn, args, kwargs): """Test checking when the function returns Truthy values.""" c = Condition("test", fn, *args, **kwargs) assert c.check()