Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit fe00d2b

Browse files
authored
CFn: configure wait time for polling resources (#13455)
1 parent 9bf66b4 commit fe00d2b

4 files changed

Lines changed: 43 additions & 5 deletions

File tree

localstack-core/localstack/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,9 @@ def populate_edge_configuration(
12111211
# EXPERIMENTAL
12121212
CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES = is_env_not_false("CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES")
12131213

1214+
# Decrease the waiting time for resource deployment
1215+
CFN_NO_WAIT_ITERATIONS: str | int | None = os.environ.get("CFN_NO_WAIT_ITERATIONS")
1216+
12141217
# bind address of local DNS server
12151218
DNS_ADDRESS = os.environ.get("DNS_ADDRESS") or "0.0.0.0"
12161219
# port of the local DNS server

localstack-core/localstack/services/cloudformation/provider.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from collections import defaultdict
66
from copy import deepcopy
77

8+
from localstack import config
89
from localstack.aws.api import CommonServiceException, RequestContext, handler
910
from localstack.aws.api.cloudformation import (
1011
AlreadyExistsException,
@@ -120,6 +121,7 @@
120121
find_stack_by_id,
121122
get_cloudformation_store,
122123
)
124+
from localstack.services.plugins import ServiceLifecycleHook
123125
from localstack.state import StateVisitor
124126
from localstack.utils.collections import (
125127
remove_attributes,
@@ -177,7 +179,30 @@ def __init__(self, message=None):
177179
super().__init__("InternalFailure", status_code=500, message=message, sender_fault=False)
178180

179181

180-
class CloudformationProvider(CloudformationApi):
182+
class CloudformationProvider(CloudformationApi, ServiceLifecycleHook):
183+
def on_before_start(self):
184+
self._validate_config()
185+
186+
def _validate_config(self):
187+
no_wait_value: int = 5
188+
try:
189+
no_wait_value = int(config.CFN_NO_WAIT_ITERATIONS or 5)
190+
except (TypeError, ValueError):
191+
LOG.warning(
192+
"You have set CFN_NO_WAIT_ITERATIONS to an invalid value: '%s'. It must be an integer greater or equal to 0. Using the default of 5",
193+
config.CFN_NO_WAIT_ITERATIONS,
194+
)
195+
196+
if no_wait_value < 0:
197+
LOG.warning(
198+
"You have set CFN_NO_WAIT_ITERATIONS to an invalid value: '%s'. It must be an integer greater or equal to 0. Using the default of 5",
199+
config.CFN_NO_WAIT_ITERATIONS,
200+
)
201+
no_wait_value = 5
202+
203+
# Set the configuration back
204+
config.CFN_NO_WAIT_ITERATIONS = no_wait_value
205+
181206
def _stack_status_is_active(self, stack_status: str) -> bool:
182207
return stack_status not in [StackStatus.DELETE_COMPLETE]
183208

localstack-core/localstack/services/cloudformation/resource_provider.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,17 +430,20 @@ def __init__(
430430
self.stack_name = stack_name
431431
self.stack_id = stack_id
432432

433+
# This should have been set up in the provider
434+
assert isinstance(config.CFN_NO_WAIT_ITERATIONS, int)
435+
433436
def deploy_loop(
434437
self,
435438
resource_provider: ResourceProvider,
436439
resource: dict,
437440
raw_payload: ResourceProviderPayload,
438441
max_timeout: int = config.CFN_PER_RESOURCE_TIMEOUT,
439-
sleep_time: float = 5,
442+
sleep_time: float = 1,
440443
) -> ProgressEvent[Properties]:
441444
payload = copy.deepcopy(raw_payload)
442445

443-
max_iterations = max(ceil(max_timeout / sleep_time), 2)
446+
max_iterations = max(ceil(max_timeout / sleep_time), 10)
444447

445448
for current_iteration in range(max_iterations):
446449
resource_type = get_resource_type({"Type": raw_payload["resourceType"]})
@@ -486,10 +489,11 @@ def deploy_loop(
486489
payload["requestData"]["resourceProperties"] = event.resource_model
487490
resource["Properties"] = event.resource_model
488491

489-
if current_iteration == 0:
490-
time.sleep(0)
492+
if current_iteration < config.CFN_NO_WAIT_ITERATIONS:
493+
pass
491494
else:
492495
time.sleep(sleep_time)
496+
493497
case OperationStatus.PENDING:
494498
# come back to this resource in another iteration
495499
return event

localstack-core/localstack/services/cloudformation/v2/provider.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ def find_stack_instance(stack_set: StackSet, account: str, region: str) -> Stack
222222

223223
class CloudformationProviderV2(CloudformationProvider, ServiceLifecycleHook):
224224
def on_before_start(self):
225+
# TODO: make sure to bring `_validate_config` from the base class when removing it
226+
# as this ensures we have a valid CFN_NO_WAIT_ITERATIONS value
227+
super().on_before_start()
228+
self._log_create_issue_info()
229+
230+
def _log_create_issue_info(self):
225231
base = "https://github.com/localstack/localstack/issues/new"
226232
query_args = {
227233
"template": "bug-report.yml",

0 commit comments

Comments
 (0)