diff --git a/lib/ansible/modules/system/iptables.py b/lib/ansible/modules/system/iptables.py index 350b396d302..7a857fe4796 100644 --- a/lib/ansible/modules/system/iptables.py +++ b/lib/ansible/modules/system/iptables.py @@ -346,8 +346,15 @@ EXAMPLES = ''' table: mangle set_dscp_mark_class: CS1 protocol: tcp + +# Set the policy for the INPUT chain to DROP +- iptables: + chain: INPUT + policy: DROP ''' +import re + # import module snippets from ansible.module_utils.basic import AnsibleModule @@ -463,6 +470,16 @@ def set_chain_policy(iptables_path, module, params): module.run_command(cmd, check_rc=True) +def get_chain_policy(iptables_path, module, params): + cmd = push_arguments(iptables_path, '-L', params) + rc, out, _ = module.run_command(cmd, check_rc=True) + chain_header = out.split("\n")[0] + result = re.search(r'\(policy ([A-Z]+)\)', chain_header) + if result: + return result.group(1) + return None + + def main(): module = AnsibleModule( supports_check_mode=True, @@ -540,18 +557,22 @@ def main(): module.fail_json( msg="Either chain or flush parameter must be specified.") # Flush the table - if args['flush']: + if args['flush'] is True: args['changed'] = True if not module.check_mode: flush_table(iptables_path, module, module.params) # Set the policy elif module.params['policy']: - args['changed'] = True - if not module.check_mode: + current_policy = get_chain_policy(iptables_path, module, module.params) + if not current_policy: + module.fail_json(msg='Can\'t detect current policy') + + changed = current_policy != module.params['policy'] + args['changed'] = changed + if changed and not module.check_mode: set_chain_policy(iptables_path, module, module.params) - # Chain else: insert = (module.params['action'] == 'insert') rule_is_present = check_present(iptables_path, module, module.params) @@ -559,15 +580,33 @@ def main(): # Check if target is up to date args['changed'] = (rule_is_present != should_be_present) + if args['changed'] is False: + # Target is already up to date + module.exit_json(**args) - if args['changed'] and not module.check_mode: + # Check only; don't modify + if not module.check_mode: if should_be_present: if insert: insert_rule(iptables_path, module, module.params) else: append_rule(iptables_path, module, module.params) else: - remove_rule(iptables_path, module, module.params) + insert = (module.params['action'] == 'insert') + rule_is_present = check_present(iptables_path, module, module.params) + should_be_present = (args['state'] == 'present') + + # Check if target is up to date + args['changed'] = (rule_is_present != should_be_present) + + if args['changed'] and not module.check_mode: + if should_be_present: + if insert: + insert_rule(iptables_path, module, module.params) + else: + append_rule(iptables_path, module, module.params) + else: + remove_rule(iptables_path, module, module.params) module.exit_json(**args)