AWS WAF module custom waiter (#37026)

Consolidate waiters to a single file

* Add waiter message with token ID
* Add waiter

Add waiter for WAF change tokens

Working waiter for waf_condition module

Add support for waiters to waf_rule

* WAF data model refactor

* Fix ref to self.client

* Add custom waiters to aws_waf_web_acl

* Allow add/remove rule tasks to operate in parallel, then wait for their change tokens to complete

* Move waiter into run_func_with_change_token_backoff since it is generic to all WAF update operations

* Wait for deletes on waf_web_acl

* Remove always-wait

* Remove waiter retry catch
This commit is contained in:
Ryan Brown 2018-04-04 21:30:57 -04:00 committed by Will Thames
commit 1c7b9e66b4
5 changed files with 82 additions and 19 deletions

View file

@ -451,7 +451,7 @@ class Condition(object):
updates.extend([{'Action': 'DELETE', 'RegexPatternString': pattern} for pattern in extra])
run_func_with_change_token_backoff(self.client, self.module,
{'RegexPatternSetId': pattern_set['RegexPatternSetId'], 'Updates': updates},
self.client.update_regex_pattern_set)
self.client.update_regex_pattern_set, wait=True)
return self.get_regex_pattern_set_with_backoff(pattern_set['RegexPatternSetId'])['RegexPatternSet']
def delete_unused_regex_pattern(self, regex_pattern_set_id):
@ -466,8 +466,10 @@ class Condition(object):
run_func_with_change_token_backoff(self.client, self.module,
{'RegexPatternSetId': regex_pattern_set_id},
self.client.delete_regex_pattern_set)
self.client.delete_regex_pattern_set, wait=True)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
if e.response['Error']['Code'] == 'WAFNonexistentItemException':
return
self.module.fail_json_aws(e, msg='Could not delete regex pattern')
def get_condition_by_name(self, name):
@ -537,6 +539,7 @@ class Condition(object):
func = getattr(self.client, 'update_' + self.method_suffix)
params = self.format_for_deletion(current_condition)
try:
# We do not need to wait for the conditiontuple delete because we wait later for the delete_* call
run_func_with_change_token_backoff(self.client, self.module, params, func)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self.module.fail_json_aws(e, msg='Could not delete filters from condition')
@ -544,7 +547,7 @@ class Condition(object):
params = dict()
params[self.conditionsetid] = condition_set_id
try:
run_func_with_change_token_backoff(self.client, self.module, params, func)
run_func_with_change_token_backoff(self.client, self.module, params, func, wait=True)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self.module.fail_json_aws(e, msg='Could not delete condition')
# tidy up regex patterns
@ -580,7 +583,7 @@ class Condition(object):
update['Updates'] = missing + extra
func = getattr(self.client, 'update_' + self.method_suffix)
try:
run_func_with_change_token_backoff(self.client, self.module, update, func)
result = run_func_with_change_token_backoff(self.client, self.module, update, func, wait=True)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
self.module.fail_json_aws(e, msg='Could not update condition')
return changed, self.get_condition_by_id(condition_set_id)

View file

@ -207,7 +207,7 @@ def find_and_update_rule(client, module, rule_id):
}
if changed:
try:
run_func_with_change_token_backoff(client, module, update, client.update_rule)
run_func_with_change_token_backoff(client, module, update, client.update_rule, wait=True)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg='Could not update rule conditions')
@ -282,7 +282,7 @@ def ensure_rule_absent(client, module):
if rule_id:
remove_rule_conditions(client, module, rule_id)
try:
return True, run_func_with_change_token_backoff(client, module, {'RuleId': rule_id}, client.delete_rule)
return True, run_func_with_change_token_backoff(client, module, {'RuleId': rule_id}, client.delete_rule, wait=True)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg='Could not delete rule')
return False, {}

View file

@ -135,6 +135,7 @@ except ImportError:
import re
from ansible.module_utils.aws.core import AnsibleAWSModule
from ansible.module_utils.aws.waiters import get_waiter
from ansible.module_utils.ec2 import boto3_conn, get_aws_connection_info, ec2_argument_spec, camel_dict_to_snake_dict
from ansible.module_utils.aws.waf import list_rules_with_backoff, list_web_acls_with_backoff, run_func_with_change_token_backoff
@ -193,18 +194,33 @@ def find_and_update_web_acl(client, module, web_acl_id):
'WebACLId': acl['WebACLId'],
'DefaultAction': acl['DefaultAction']
}
change_tokens = []
if deletions:
try:
params['Updates'] = deletions
run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
result = run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
change_tokens.append(result['ChangeToken'])
get_waiter(
client, 'change_token_in_sync',
).wait(
ChangeToken=result['ChangeToken']
)
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg='Could not update Web ACL')
if insertions:
try:
params['Updates'] = insertions
run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
result = run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
change_tokens.append(result['ChangeToken'])
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg='Could not update Web ACL')
if change_tokens:
for token in change_tokens:
get_waiter(
client, 'change_token_in_sync',
).wait(
ChangeToken=token
)
if changed:
acl = get_web_acl(client, module, web_acl_id)
return changed, acl
@ -261,7 +277,7 @@ def ensure_web_acl_absent(client, module):
if web_acl['Rules']:
remove_rules_from_web_acl(client, module, web_acl_id)
try:
run_func_with_change_token_backoff(client, module, {'WebACLId': web_acl_id}, client.delete_web_acl)
run_func_with_change_token_backoff(client, module, {'WebACLId': web_acl_id}, client.delete_web_acl, wait=True)
return True, {}
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg='Could not delete Web ACL')