Skip to content

Commit f704aed

Browse files
committed
updates
1 parent 2406b5a commit f704aed

File tree

5 files changed

+93
-84
lines changed

5 files changed

+93
-84
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## 1.9.3 (2025-10-16)
3+
## 1.9.4 (2025-10-16)
44

55
- added `--output-file` argument
66
- added stack level `exports` - pre defined `stack_name`, `stack_env`, `elapsed_time` and user defined

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
setup(
1212
name='stackql-deploy',
13-
version='1.9.3',
13+
version='1.9.4',
1414
description='Model driven resource provisioning and deployment framework using StackQL.',
1515
long_description=readme,
1616
long_description_content_type='text/x-rst',

stackql_deploy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.9.3'
1+
__version__ = '1.9.4'

stackql_deploy/cmd/build.py

Lines changed: 88 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -159,44 +159,102 @@ def run(self, dry_run, show_queries, on_failure, output_file=None):
159159
ignore_errors = True
160160

161161
#
162-
# OPTIMIZED exists and state check - try exports first for happy path
162+
# State checking logic
163163
#
164164
exports_result_from_proxy = None # Track exports result if used as proxy
165165

166166
if createorupdate_query:
167+
# Skip all existence and state checks for createorupdate
167168
pass
168169
else:
169-
# OPTIMIZATION: Try exports first if available for one-query solution
170-
if exports_query:
170+
# Determine the validation strategy based on available queries
171+
if statecheck_query:
172+
#
173+
# Flow 1: Traditional flow when statecheck exists
174+
# exists → create/update → statecheck → exports
175+
#
176+
if exists_query:
177+
resource_exists = self.check_if_resource_exists(
178+
resource_exists,
179+
resource,
180+
full_context,
181+
exists_query,
182+
exists_retries,
183+
exists_retry_delay,
184+
dry_run,
185+
show_queries
186+
)
187+
else:
188+
# Use statecheck as exists check
189+
is_correct_state = self.check_if_resource_is_correct_state(
190+
is_correct_state,
191+
resource,
192+
full_context,
193+
statecheck_query,
194+
statecheck_retries,
195+
statecheck_retry_delay,
196+
dry_run,
197+
show_queries
198+
)
199+
resource_exists = is_correct_state
200+
201+
# Pre-deployment state check for existing resources
202+
if resource_exists and not is_correct_state:
203+
if resource.get('skip_validation', False):
204+
self.logger.info(
205+
f"skipping validation for [{resource['name']}] as skip_validation is set to true."
206+
)
207+
is_correct_state = True
208+
else:
209+
is_correct_state = self.check_if_resource_is_correct_state(
210+
is_correct_state,
211+
resource,
212+
full_context,
213+
statecheck_query,
214+
statecheck_retries,
215+
statecheck_retry_delay,
216+
dry_run,
217+
show_queries
218+
)
219+
220+
elif exports_query:
221+
#
222+
# Flow 2: Optimized flow when only exports exists (no statecheck)
223+
# Try exports first with FAST FAIL (no retries)
224+
# If fails: exists → create/update → exports (with retries as statecheck)
225+
#
171226
self.logger.info(
172-
f"🔄 trying exports query first for optimal single-query validation "
227+
f"🔄 trying exports query first (fast-fail) for optimal validation "
173228
f"for [{resource['name']}]"
174229
)
175230
is_correct_state, exports_result_from_proxy = self.check_state_using_exports_proxy(
176231
resource,
177232
full_context,
178233
exports_query,
179-
exports_retries,
180-
exports_retry_delay,
234+
1, # Fast fail: only 1 attempt
235+
0, # No delay
181236
dry_run,
182237
show_queries
183238
)
184239
resource_exists = is_correct_state
185240

186-
# If exports succeeded, we're done with validation for happy path
241+
# If exports succeeded, we're done with validation (happy path)
187242
if is_correct_state:
188243
self.logger.info(
189-
f"✅ [{resource['name']}] validated successfully with single exports query"
244+
f"✅ [{resource['name']}] validated successfully with fast exports query"
190245
)
191246
else:
192-
# If exports failed, fall back to traditional exists check
247+
# Exports failed, fall back to exists check
193248
self.logger.info(
194-
f"📋 exports validation failed, falling back to exists check "
249+
f"📋 fast exports validation failed, falling back to exists check "
195250
f"for [{resource['name']}]"
196251
)
252+
# Clear the failed exports result
253+
exports_result_from_proxy = None
254+
197255
if exists_query:
198256
resource_exists = self.check_if_resource_exists(
199-
False, # Reset this since exports failed
257+
False,
200258
resource,
201259
full_context,
202260
exists_query,
@@ -205,23 +263,14 @@ def run(self, dry_run, show_queries, on_failure, output_file=None):
205263
dry_run,
206264
show_queries
207265
)
208-
elif statecheck_query:
209-
# statecheck can be used as an exists check fallback
210-
is_correct_state = self.check_if_resource_is_correct_state(
211-
False, # Reset this
212-
resource,
213-
full_context,
214-
statecheck_query,
215-
statecheck_retries,
216-
statecheck_retry_delay,
217-
dry_run,
218-
show_queries
219-
)
220-
resource_exists = is_correct_state
221-
# Reset is_correct_state since we need to re-validate after create/update
222-
is_correct_state = False
266+
else:
267+
# No exists query, assume resource doesn't exist
268+
resource_exists = False
269+
223270
elif exists_query:
224-
# Traditional path: exports not available, use exists
271+
#
272+
# Flow 3: Basic flow with only exists query
273+
#
225274
resource_exists = self.check_if_resource_exists(
226275
resource_exists,
227276
resource,
@@ -232,59 +281,12 @@ def run(self, dry_run, show_queries, on_failure, output_file=None):
232281
dry_run,
233282
show_queries
234283
)
235-
elif statecheck_query:
236-
# statecheck can be used as an exists check
237-
is_correct_state = self.check_if_resource_is_correct_state(
238-
is_correct_state,
239-
resource,
240-
full_context,
241-
statecheck_query,
242-
statecheck_retries,
243-
statecheck_retry_delay,
244-
dry_run,
245-
show_queries
246-
)
247-
resource_exists = is_correct_state
248284
else:
249285
catch_error_and_exit(
250286
"iql file must include either 'exists', 'statecheck', or 'exports' anchor.",
251287
self.logger
252288
)
253289

254-
#
255-
# state check with optimizations (only if we haven't already validated via exports)
256-
#
257-
if resource_exists and not is_correct_state and exports_result_from_proxy is None:
258-
# bypass state check if skip_validation is set to true
259-
if resource.get('skip_validation', False):
260-
self.logger.info(
261-
f"skipping validation for [{resource['name']}] as skip_validation is set to true."
262-
)
263-
is_correct_state = True
264-
elif statecheck_query:
265-
is_correct_state = self.check_if_resource_is_correct_state(
266-
is_correct_state,
267-
resource,
268-
full_context,
269-
statecheck_query,
270-
statecheck_retries,
271-
statecheck_retry_delay,
272-
dry_run,
273-
show_queries
274-
)
275-
elif exports_query:
276-
# This shouldn't happen since we tried exports first, but keeping for safety
277-
self.logger.info(f"🔄 using exports query as proxy for statecheck for [{resource['name']}]")
278-
is_correct_state, _ = self.check_state_using_exports_proxy(
279-
resource,
280-
full_context,
281-
exports_query,
282-
exports_retries,
283-
exports_retry_delay,
284-
dry_run,
285-
show_queries
286-
)
287-
288290
#
289291
# resource does not exist
290292
#
@@ -319,10 +321,11 @@ def run(self, dry_run, show_queries, on_failure, output_file=None):
319321
)
320322

321323
#
322-
# check state again after create or update with optimizations
324+
# check state again after create or update
323325
#
324326
if is_created_or_updated:
325327
if statecheck_query:
328+
# Use statecheck for post-deploy validation
326329
is_correct_state = self.check_if_resource_is_correct_state(
327330
is_correct_state,
328331
resource,
@@ -334,17 +337,23 @@ def run(self, dry_run, show_queries, on_failure, output_file=None):
334337
show_queries,
335338
)
336339
elif exports_query:
337-
# OPTIMIZATION: Use exports as statecheck proxy for post-deploy validation
340+
# Use exports as statecheck proxy with proper retries
341+
# This handles the case where statecheck doesn't exist
338342
self.logger.info(
339-
f"🔄 using exports query as proxy for post-deploy statecheck "
343+
f"🔄 using exports query as post-deploy statecheck "
340344
f"for [{resource['name']}]"
341345
)
346+
# Need to determine retries: if we have statecheck config, use it
347+
# Otherwise fall back to exports config
348+
post_deploy_retries = statecheck_retries if statecheck_retries > 1 else exports_retries
349+
post_deploy_delay = statecheck_retry_delay if statecheck_retries > 1 else exports_retry_delay
350+
342351
is_correct_state, exports_result_from_proxy = self.check_state_using_exports_proxy(
343352
resource,
344353
full_context,
345354
exports_query,
346-
exports_retries,
347-
exports_retry_delay,
355+
post_deploy_retries,
356+
post_deploy_delay,
348357
dry_run,
349358
show_queries
350359
)

stackql_deploy/cmd/test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ def run(self, dry_run, show_queries, on_failure, output_file=None):
108108
resource,
109109
full_context,
110110
exports_query,
111-
exports_retries,
112-
exports_retry_delay,
111+
statecheck_retries, # Use statecheck retries when using as statecheck proxy
112+
statecheck_retry_delay, # Use statecheck delay when using as statecheck proxy
113113
dry_run,
114114
show_queries
115115
)

0 commit comments

Comments
 (0)