Skip to content

Commit 4bb52f2

Browse files
committed
fix(nfs): handle eventual consistency during status polling
- Track last valid share response to avoid using error responses for final status check - Handle API returning 200 with error payload (NotFound) during polling - Increase database_replica test timeout to 600s for forking operations
1 parent 2bedab1 commit 4bb52f2

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

plugins/modules/nfs.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ def create_nfs_share(self):
217217
)
218218

219219
# Wait for the NFS share to become active
220+
# NFS API has eventual consistency - share may not be queryable immediately
220221
end_time = time.monotonic() + self.timeout
222+
last_valid_share = nfs_share # Keep track of last valid share response
221223
while time.monotonic() < end_time:
222224
status = nfs_share.get("status", "").upper()
223225
if status == "ACTIVE":
@@ -232,13 +234,25 @@ def create_nfs_share(self):
232234
try:
233235
# get() requires region parameter
234236
response = self.client.nfs.get(nfs_id=nfs_id, region=self.region)
237+
# Check if response is an error (API may return 200 with error payload)
238+
if (
239+
response.get("code")
240+
or response.get("message") == "share not found"
241+
):
242+
self.module.warn(
243+
f"NFS share {nfs_id} not found during polling, continuing..."
244+
)
245+
# Don't update nfs_share - keep last valid response
246+
continue
235247
nfs_share = response.get("share", response)
248+
last_valid_share = nfs_share
236249
except DigitalOceanCommonModule.HttpResponseError as err:
237250
# If get fails, log warning but continue polling
238251
error_msg = err.error.message if err.error else str(err)
239252
self.module.warn(f"Failed to fetch NFS share status: {error_msg}")
240253

241-
# Check final status after timeout
254+
# Use last valid share for final status check
255+
nfs_share = last_valid_share
242256
final_status = nfs_share.get("status", "").upper()
243257
if final_status != "ACTIVE":
244258
self.module.fail_json(
@@ -303,7 +317,9 @@ def present(self):
303317
nfs_id = nfs_share.get("id")
304318

305319
# Wait for the NFS share to become active if it's still creating
320+
# NFS API has eventual consistency - share may not be queryable immediately
306321
end_time = time.monotonic() + self.timeout
322+
last_valid_share = nfs_share # Keep track of last valid share response
307323
while time.monotonic() < end_time:
308324
status = nfs_share.get("status", "").upper()
309325
if status == "ACTIVE":
@@ -318,13 +334,25 @@ def present(self):
318334
time.sleep(DigitalOceanConstants.SLEEP)
319335
try:
320336
response = self.client.nfs.get(nfs_id=nfs_id, region=self.region)
337+
# Check if response is an error (API may return 200 with error payload)
338+
if (
339+
response.get("code")
340+
or response.get("message") == "share not found"
341+
):
342+
self.module.warn(
343+
f"NFS share {nfs_id} not found during polling, continuing..."
344+
)
345+
# Don't update nfs_share - keep last valid response
346+
continue
321347
nfs_share = response.get("share", response)
348+
last_valid_share = nfs_share
322349
except DigitalOceanCommonModule.HttpResponseError as err:
323350
# If get fails, log warning but continue polling
324351
error_msg = err.error.message if err.error else str(err)
325352
self.module.warn(f"Failed to fetch NFS share status: {error_msg}")
326353

327-
# Check final status after timeout
354+
# Use last valid share for final status check
355+
nfs_share = last_valid_share
328356
final_status = nfs_share.get("status", "").upper()
329357
if final_status != "ACTIVE":
330358
self.module.fail_json(

tests/integration/targets/database_replica/tasks/01_test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
name: "{{ replica_name }}"
88
region: "{{ region }}"
99
size: "{{ replica_size }}"
10+
timeout: 600
1011
register: result
1112

1213
- name: 01_test | Verify create replica

0 commit comments

Comments
 (0)